keyongtech


  keyongtech > c > 10/2008

 #136  
09-18-08, 11:42 AM
arnuld
> On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:

>> arnuld wrote:


> Lots of people /would/ write it like that. In *my* code, I consider an
> "early return" like that to be a bug that I should fix, because in *my*
> code I want every function and every loop to have *one* entry point and
> *one* exit point. I find that this makes my programs much easier to read
> and thus to maintain.


Will not that make the program less efficient as program has to go till it
finds the return ?



>> **pw = calloc( arr_size, sizeof **pw );


> Surely you mean *pw = calloc( arr_size, sizeof **pw );



you say that calloc() will automatically return a pointer to pointer ?


> Oh, by the way - I don't see the bit where you point the array's
> elements to words. Why isn't get_words calling get_single_word?



because I did not wrote it yet ;) . I wanted to remove some confusions
first and then proceed ahead.
 #137  
09-18-08, 12:16 PM
Richard Heathfield
arnuld said:

>> On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:

>
>>> arnuld wrote:

>
>> Lots of people /would/ write it like that. In *my* code, I consider an
>> "early return" like that to be a bug that I should fix, because in *my*
>> code I want every function and every loop to have *one* entry point and
>> *one* exit point. I find that this makes my programs much easier to read
>> and thus to maintain.

>
> Will not that make the program less efficient as program has to go till
> it finds the return ?


Only if the compiler is really brain-damaged.

Let's say the code is:

if(ptr != NULL) /* A */
{
/* lots of code, translating to 500 bytes of assembly instructions */
}

return ptr; /* B */

The compiler will do something like this:

CMP ptr, 0
JE _B
(500 bytes of assembly instructions here)
_B:
MOV RR, ptr

On the second pass, JE _B will be translated into a jump to a specific
(relocatable) address, and the jump will consist simply of changing the
instruction pointer to have that new value. The program doesn't have to
"go till it finds the return" - it simply has to assign a new value to the
instruction pointer, and it doesn't give tuppence whether that value is
close to the value it had before or not.

>>> **pw = calloc( arr_size, sizeof **pw );

>
>> Surely you mean *pw = calloc( arr_size, sizeof **pw );
>> you say that calloc() will automatically return a pointer to pointer ?


No, calloc returns void * - and I don't see the relevance of your question
to the point I made.
 #138  
09-18-08, 12:58 PM
arnuld
> On Thu, 18 Sep 2008 11:16:13 +0000, Richard Heathfield wrote:

> Only if the compiler is really brain-damaged.
>
> Let's say the code is:
>
> if(ptr != NULL) /* A */
> {
> /* lots of code, translating to 500 bytes of assembly instructions */
> }
>
> return ptr; /* B */
>
> The compiler will do something like this:
>
> CMP ptr, 0
> JE _B
> (500 bytes of assembly instructions here)
> _B:
> MOV RR, ptr



hey.. thats assembly :)

> On the second pass, JE _B will be translated into a jump to a specific
> (relocatable) address, and the jump will consist simply of changing the
> instruction pointer to have that new value. The program doesn't have to
> "go till it finds the return" - it simply has to assign a new value to the
> instruction pointer, and it doesn't give tuppence whether that value is
> close to the value it had before or not.


Nobody taught me that way on comp.lang.c++. Seems like C is very closer to
assembly language.



> No, calloc returns void * - and I don't see the relevance of your
> question to the point I made.



I quoted the wrong code. See this code:

char*** pw;
*pw = calloc( arr_size, sizeof **pw );


*pw means pointer to pointer. I want to dynamically allocate an array of
pointers. but calloc() gives void* in return not void**. So how can
I dynamically allocate an array of pointers. The array elements (pointers)
will point to words ,which again are pointers.


This is going to be base for get_words function, which will be passed the
address of a pointer to pointer, making the 3 levels of indirection coming
into the picture.
 #139  
09-18-08, 01:15 PM
Richard Heathfield
arnuld said:

>>

> hey.. thats assembly :)


When we're talking about efficiency (and it was you who raised the
subject), the language definition is no longer adequate, because it
doesn't have anything to say about efficiency, so we have to look at
typical characteristics of implementations, knowing that what we say is no
longer universally true. Note that the assembly language above was only
mildly modelled on real assembly languages, and probably won't do you much
good if you try to insert it into your own program.

>> On the second pass, JE _B will be translated into a jump to a specific
>> (relocatable) address, and the jump will consist simply of changing the
>> instruction pointer to have that new value. The program doesn't have to
>> "go till it finds the return" - it simply has to assign a new value to
>> the instruction pointer, and it doesn't give tuppence whether that value
>> is close to the value it had before or not.

>
> Nobody taught me that way on comp.lang.c++.


Well, nobody would have taught you that way on comp.lang.c either, except
that you raised the subject of efficiency and suggested that a particular
style is inefficient. To demonstrate that it isn't could not be done from
within the context of the language itself.

> Seems like C is very closer to assembly language.


Yes, except that there really isn't any such thing as "assembly language" -
rather, there are many different assembly languages.

> char*** pw;
> *pw = calloc( arr_size, sizeof **pw );
>> *pw means pointer to pointer. I want to dynamically allocate an array of

> pointers. but calloc() gives void* in return not void**.


Right. (So do malloc and realloc.) Why would you need void **?

> So how can
> I dynamically allocate an array of pointers.


T **p;
p = malloc(n * sizeof *p);
if(p != NULL)
{
p[0] through p[n - 1] are now pointers to T, with indeterminate values

If you are passing p via a function parameter, you will need an additional
level of indirection, so take it as T ***p and do:

*p = malloc(n * sizeof **p);
if(*p != NULL)
{
(*p)[0] through (*p)[n - 1] are now pointers to T...
 #140  
09-18-08, 02:06 PM
arnuld
> On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:

> ...SNIP..


> Surely you mean *pw = calloc( arr_size, sizeof **pw );
>
> Oh, by the way - I don't see the bit where you point the array's elements
> to words. Why isn't get_words calling get_single_word?



Okay here is my new code:



#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>


enum { WORD_SIZE = 28, ARRSIZE = 10 };

enum { GSW_OK, GSW_ENOMEM, GSW_ENORESIZE } ;

enum { GW_OK, GW_ENOMEM, GW_ENORESIZE };


int get_words( char***, size_t* );
int get_single_word( char** );


int main( void )
{
char** pword; /* pw means pointer to word */
size_t word_count;
int num;

pword = NULL;
word_count = 0;

num = get_words( &pword, &word_count );

printf("words = %d, num = %d\n", (int) word_count, num);



free(pword);

return 0;
}


int get_words( char*** pw, size_t* cnt )
{
size_t idx;
int mem_check;
char **pw_begin, **new_mem;
char* pword;
size_t arr_size;

arr_size = ARRSIZE;
mem_check = GW_ENOMEM;

*pw = calloc( arr_size, sizeof **pw );
pw_begin = *pw;

if( *pw )
{
mem_check = GW_OK;
pw_begin = *pw;


for( idx = 0; (! get_single_word( &pword )) && *pword; ++idx )
{
if( idx == arr_size )
{
new_mem = realloc( **pw, (2 * arr_size * sizeof new_mem));

if( new_mem )
{
pw_begin = new_mem;
}
else
{
mem_check = GW_ENORESIZE;
}
}

if( GSW_OK == mem_check )
{
pw_begin++ = &pword;
}
}

pw_begin = NULL;

}

*cnt = idx;

return mem_check;
}




int get_single_word( char** pc )
{
int mem_check;
unsigned idx;
int ch;

size_t curr_size;
char *new_mem;
char *pc_begin;

mem_check = GSW_ENOMEM; /* will updat eit on first use */
curr_size = WORD_SIZE;

*pc = calloc(curr_size, sizeof(**pc));

if( (! *pc) )
{
mem_check = GSW_ENOMEM;
return mem_check;
}
else
{
mem_check = GSW_OK;
pc_begin = *pc;
}



while( (ch = getchar()) && (isspace( (unsigned char) ch)) )
{
continue; /* skip leading white space */
}


if( EOF != ch )
{
*pc_begin++ = ch;
}

while( (GSW_OK == mem_check) &&
((ch = getchar()) != EOF) &&
(! isspace( (unsigned char) ch)) )
{
if( idx == curr_size )
{
new_mem = realloc( pc_begin, (2 * curr_size * sizeof(*new_mem)));

if( new_mem )
{
pc_begin = new_mem;
curr_size *= 2;
}
else
{
mem_check = GSW_ENORESIZE; /* error, couldn't not enlarge */
*pc_begin = '\0';
return mem_check;
}
}

if( GSW_OK == mem_check )
{
*pc_begin++ = ch;
}

}


*pc_begin = '\0';


return mem_check;
}

======================= OUTPUT ========================
[arnuld@dune ztest]$ gcc -ansi -pedantic -Wall -Wextra sort-input.c
sort-input.c: In function `get_words':
sort-input.c:79: error: invalid lvalue in assignment
[arnuld@dune ztest]$



Line 79: pw_begin++ = &pword;

I don't understand why I am getting this error.
 #141  
09-18-08, 02:25 PM
Richard Heathfield
arnuld said:

<snip>

> Line 79: pw_begin++ = &pword;
>
> I don't understand why I am getting this error.


The assignment operator requires a modifiable lvalue as its left operand.
The ++ operator yields a value as its result. The above is equivalent in
spirit to a statement such as: 6 = &pword; which simply makes no sense.
The implementation is obliged to diagnose this, and has done so.

What you meant to write is:

*pw_begin++ = pword;

This is legal because * has higher precedence than = so what happens is
that ++ yields the old value of pw_begin, * gives us the object to which
that old value points, and = now assigns to the object. Since pw_begin has
type char **, pw_begin++ has type char **, *pw_begin++ has type char * and
is a real object, so we can assign a char * value to it. pword is one such
value.
 #142  
09-18-08, 02:26 PM
James Kuyper
arnuld wrote:
....
>> *pc = calloc(cursize, sizeof **pc);
>> if(*pc != NULL)
>> {

....
> This whole program is based on that condition of *pc != NULL. Why don't
> we put a line like, *pc == NULL and then return from the program with the
> ENOMEM value right there ?


If you return from the program, the fact that errno contains ENOMEM has
no further significance.
 #143  
09-18-08, 02:31 PM
James Kuyper
Richard Heathfield wrote:
....
> The compiler will do something like this:
>
> CMP ptr, 0
> JE _B
> (500 bytes of assembly instructions here)
> _B:
> MOV RR, ptr
>
> On the second pass, JE _B will be translated into a jump to a specific
> (relocatable) address, and the jump will consist simply of changing the
> instruction pointer to have that new value. The program doesn't have to
> "go till it finds the return" - it simply has to assign a new value to the
> instruction pointer, and it doesn't give tuppence whether that value is
> close to the value it had before or not.


It depends upon the assembly language; I've written assembly in
languages where a short jump used a faster instruction than a long jump.
However, it was only a little bit faster; not enough to justify worrying
about in C code.
 #144  
09-18-08, 02:41 PM
James Kuyper
Richard Heathfield wrote:
> arnuld said:

....
>> My meaning of academic means, "being not practical" . In Indian computer
>> education system, clrscr() is the function that belongs to a language
>> named TURBO C, which is better than C.

>
> I've never heard such baloney. C is a language. Turbo C is an ancient
> implementation, no longer supported, which runs on only one tiny class of
> platforms.
>
>> There is *only* one good C and that is TURBO C.

>
> Try telling that to the OS390 guys.


I would imagine, since he prefaced his statement with "In Indian
computer education system ...", that this would imply that the specified
system doesn't have any OS390 guys. He wasn't making a more general
statement. The wording of his statement leaves open the possibility that
there are implementations of C which are better than the ones he listed,
they just don't happen to be available in that system. If this is the
case, he has my sympathy - I thought the Indians were more advanced than
that.

However, India is a huge place, and I doubt that arnuld has seen the
entire "Indian computer education system". I suspect that he's
describing the attitude of one particular piece (of unknown size) of
that system. However, his description of that piece of the system might
be perfectly accurate.
 #145  
09-18-08, 03:52 PM
Ben Bacarisse
arnuld <sunrise> writes:

>> On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:

<snip>
> Okay here is my new code:


A few comments.

[..]
> *pw = calloc( arr_size, sizeof **pw );
> pw_begin = *pw;
>
> if( *pw )
> {
> mem_check = GW_OK;
> pw_begin = *pw;
>> for( idx = 0; (! get_single_word( &pword )) && *pword; ++idx )


I find this counter-intuitive. I had to go check what get_single_word
returns for success (GSW_OK) and then go check that this was indeed
zero so ! of it was true. I'd write

> for( idx = 0; get_single_word( &pword ) == GSW_OK; ++idx )


and try hard to make sure that there is no need for the extra check
on *pword. I have not checked if you need it.

> {
> if( idx == arr_size )
> {
> new_mem = realloc( **pw, (2 * arr_size * sizeof new_mem));
>
> if( new_mem )
> {
> pw_begin = new_mem;


Surely not? The next words has to go after the existing ones in the new
memory not at the start.

> }
> else
> {
> mem_check = GW_ENORESIZE;
> }
> }
>
> if( GSW_OK == mem_check )


This looks wrong. You set mem_check only once and that is to GW_OK.
Now GW_OK == GSW_OK (probably) but why test it anyway since we are in
an the if where it was set? I.e. you get to this test unless
mem_check is GW_OK.

> {
> pw_begin++ = &pword;
> }
> }


I find this a gruesome waste of space, but that is only style! You go
with what feels right.

[..]
> }
> else
> {
> mem_check = GSW_OK;
> pc_begin = *pc;
> }
>>

> while( (ch = getchar()) && (isspace( (unsigned char) ch)) )


Ah! The cast is wrong here. Not just unneeded, but wrong. I'll
gladly say why but I think you get way more out of it if you can work
out why for yourself. It won't actually fail o any system that I can
recall but it is, technically, not portable.

> {
> continue; /* skip leading white space */
> }
>> if( EOF != ch )

> {
> *pc_begin++ = ch;
> }
>
> while( (GSW_OK == mem_check) &&
> ((ch = getchar()) != EOF) &&
> (! isspace( (unsigned char) ch)) )


And here it is unneeded but can't, even theoretically, cause a
problem.

> {
> if( idx == curr_size )
> {
> new_mem = realloc( pc_begin, (2 * curr_size * sizeof(*new_mem)));
>
> if( new_mem )
> {
> pc_begin = new_mem;


Again, is this right? New characters need to go after the ones that
are there already.
[..]
 #146  
09-18-08, 05:10 PM
Keith Thompson
arnuld <sunrise> writes:
>> On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:

[...]
>>> **pw = calloc( arr_size, sizeof **pw );

>
>> Surely you mean *pw = calloc( arr_size, sizeof **pw );
>> you say that calloc() will automatically return a pointer to pointer ?

[...]

No, calloc() returns a void*. The assignment implicitly converts that
void* result to the type of the left side; in this case, whatever type
*pw has.
 #147  
09-18-08, 06:46 PM
arnuld
> On Thu, 18 Sep 2008 13:41:08 +0000, James Kuyper wrote:

> I thought the Indians were more advanced than that.


You are wrong. Most Indian students say that you need Windows to run a
computer, without Windows you can not use a computer. I have yet to meet a
person who uses Linux as his daily use OS.



> However, India is a huge place, and I doubt that arnuld has seen the
> entire "Indian computer education system". I suspect that he's
> describing the attitude of one particular piece (of unknown size) of
> that system.


I am graduated from "Panjab University", one of the top 4 most respected
universities in India. You can think about what rest of will be like. 2nd,
other than these top 4, most do not eve have proper working hardware
available to them. Most shocking fact is that you won't find a computer
teachers, even if you find institute.

Only *a few* are good, hear of IIT, Indian Institute of Technology, a
supreme quality Engg. College with 5 or 8 branches all over India. It is
the only institute which gives quality education.

I met a programmer, 2 years ago, he asked me what I am doing at that time.
I said I was reading Haskell, he had first devision in his Computer
Science Engg. degree and was earning 20,000 rupees a month. He asked me
"What is Husk... a..all.... some sort of Fictional Novel ? ".... :-\
 #148  
09-18-08, 07:44 PM
Default User
arnuld wrote:

> > On Thu, 18 Sep 2008 09:04:49 +0000, Richard Heathfield wrote:

>
> > I've never heard such baloney. C is a language. Turbo C is an
> > ancient implementation, no longer supported, which runs on only one
> > tiny class of platforms.

>
> I did not know that TURBO C is an ancient compiler. As of 2008, the
> Indian Computer Education system still rely on TURBO C compiler.



That's because it's free.




Brian
 #149  
09-18-08, 07:52 PM
Default User
Andrew Poelstra wrote:

> On 2008-09-17, arnuld <sunrise> wrote:
> >
> > My meaning of academic means, "being not practical" . In Indian
> > computer education system, clrscr() is the function that belongs to
> > a language named TURBO C, which is better than C. There is only one
> > good C and that is TURBO C. Same for VC++ which, of course , is
> > much better than C++. Microsoft has created a better language than
> > C.
> >

>
> Well, TURBO C is not C, and VC++ is not C++. Microsoft should not have
> named their products so similarly to those real languages.


Then you should the same complaint about gcc and almost every other C
implementation. Almost all offer some sort of extensions.

Turbo C contained a nearly conforming C89 compiler. I believe I've
heard that there were a few bugs, but I don't recall what they were.
The manual had a portability statement for every library function
included that specified whether it was ANSI C, UNIX, or
platform-specific.

Oh, and Turbo C was Borland, not Microsoft.




Brian
 #150  
09-18-08, 08:02 PM
Default User
Richard Heathfield wrote:

> arnuld said:


> > This whole program is based on that condition of *pc != NULL. Why
> > don't we put a line like, *pc == NULL and then return from the
> > program with the ENOMEM value right there ?

>
> Lots of people would write it like that. In my code, I consider an
> "early return" like that to be a bug that I should fix, because in my
> code I want every function and every loop to have one entry point and
> one exit point. I find that this makes my programs much easier to
> read and thus to maintain.


Our company coding standard now allows early return for initial
parameter checking. In the old days, the usual method was something
like:

int func(int a, int b)
{
returnval = 0;

if (a > 10)
{
returnval = -1;
}
else if (b > 20)
{
returnval = -2;
}

if (returnval == 0)
{
/* do the real work and set returnval appropriately */
}

return returnval;
}

Now you can do:

int func(int a, int b)
{
returnval = 0;

if (a > 10)
{
return -1;
}
if (b > 20)
{
return -2;
}

/* do the real work and set returnval appropriately */

return returnval;
}


I don't know if it's better, worse, or just differently-abled.



Brian

Similar Threads
Best way to input from stdin?

I'm writing a program that supports input from stdin. To be able to do that I tend to rely on a simple loop that tests the return of fgets(), such as the following...

How to accept input from stdin?

Hi, I try to make a wrapper around an existing program, which would behave exactly the same as the original one. But my following attempt was failed. Would you pleaes let me...

Input using stdin

How can I give input to a program using STDIN Suppose I want the program to take the value x=10 On some other site i found it as STDIN.read,but its not working.

getting input from stdin

Hi Im new to unix scripting and now Im trying to get user input from stdin and this is what I did echo "enter your name: " read name and it will run with the pointer to...

Checking available input on stdin

I know this has probably come up frequently, but couldn't find a satisfactory reference... I have some code which needs to read from stdin but must not block waiting for...


All times are GMT. The time now is 06:08 AM. | Privacy Policy