Re: [DNG] Making sense of C pointer syntax.
Hi, Thanks for the feedback. I applied the suggested changes to Makefile and git push-ed to repository. There is still a non-fatal error about linking against unnecessary libraries that has to be debugged. I will git push as soon as I find a solution. Edward On 25/05/2016, aitor_czr wrote: > > El 25/05/16 a las 10:50, aitor_czr escribió: >> Hi Edward, >> >> El 29/03/16 a las 00:58, Edward Bartolo escribió: >>> I found using the return value of a function makes code much more >>> >readable and probably more reliable. Multiple return values can be >>> >encapsulated inside a structure which would be returned by a function. >>> >I used this construct in simple-netaid-lightweight which avoids the >>> >use of GtkBuilder. >>> > >>> >Edward >> >> Building your simple-netaid-lightweight, this is what i get: >> >> >> aitor@localhost:~/simple-netaid-lightweight$ make >> rm -f sn-lightweight >> gcc -Iinclude `pkg-config --libs --cflags gtk+-2.0` -c >> src/auxiliaries.c src/signal_functions.c src/main_gui.c >> src/dialog_gui.c rc/sn-lightweight.c >> mv *.o obj/ >> mv: el objetivo «obj/» no es un directorio >> Makefile:16: recipe for target 'compile-objs' failed >> make: *** [compile-objs] Error 1 >> >> >> >> So, you need to modify the Makefile to something like this: >> >> CC=gcc >> CFLAGS=-Iinclude >> GTK2FLAGS=`pkg-config --libs --cflags gtk+-2.0` >> D=src >> OBJ=obj >> >> src0=auxiliaries.c signal_functions.c main_gui.c >> src1=dialog_gui.c sn-lightweight.c >> >> SOURCEFILES=$(addprefix $(D)/, $(src0) $(src1)) >> OBJFILES=$(addprefix $(OBJ)/, $(src0:.c=.o) $(src1:.c=.o)) >> >> all: clean compile-objs sn-lightweight >> >> compile-objs: >> $(CC) $(CFLAGS) $(GTK2FLAGS) -c $(SOURCEFILES) >> mkdir obj >> mv *.o obj/ >> >> sn-lightweight: >> $(CC) $(CFLAGS) $(GTK2FLAGS) -o sn-lightweight $(OBJFILES) >> >> clean: >> rm -f sn-lightweight >> >> After doing this change, it works :) >> >> Cheers, >> >> Aitor. >> >> [*] Added "mkdir obj" line. >> > > You must also include: > > rm -rf obj > > at the end of the Makefile. > >Aitor. > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
El 25/05/16 a las 10:50, aitor_czr escribió: Hi Edward, El 29/03/16 a las 00:58, Edward Bartolo escribió: I found using the return value of a function makes code much more >readable and probably more reliable. Multiple return values can be >encapsulated inside a structure which would be returned by a function. >I used this construct in simple-netaid-lightweight which avoids the >use of GtkBuilder. > >Edward Building your simple-netaid-lightweight, this is what i get: aitor@localhost:~/simple-netaid-lightweight$ make rm -f sn-lightweight gcc -Iinclude `pkg-config --libs --cflags gtk+-2.0` -c src/auxiliaries.c src/signal_functions.c src/main_gui.c src/dialog_gui.c rc/sn-lightweight.c mv *.o obj/ mv: el objetivo «obj/» no es un directorio Makefile:16: recipe for target 'compile-objs' failed make: *** [compile-objs] Error 1 So, you need to modify the Makefile to something like this: CC=gcc CFLAGS=-Iinclude GTK2FLAGS=`pkg-config --libs --cflags gtk+-2.0` D=src OBJ=obj src0=auxiliaries.c signal_functions.c main_gui.c src1=dialog_gui.c sn-lightweight.c SOURCEFILES=$(addprefix $(D)/, $(src0) $(src1)) OBJFILES=$(addprefix $(OBJ)/, $(src0:.c=.o) $(src1:.c=.o)) all: clean compile-objs sn-lightweight compile-objs: $(CC) $(CFLAGS) $(GTK2FLAGS) -c $(SOURCEFILES) mkdir obj mv *.o obj/ sn-lightweight: $(CC) $(CFLAGS) $(GTK2FLAGS) -o sn-lightweight $(OBJFILES) clean: rm -f sn-lightweight After doing this change, it works :) Cheers, Aitor. [*] Added "mkdir obj" line. You must also include: rm -rf obj at the end of the Makefile. Aitor. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi Edward, El 29/03/16 a las 00:58, Edward Bartolo escribió: I found using the return value of a function makes code much more >readable and probably more reliable. Multiple return values can be >encapsulated inside a structure which would be returned by a function. >I used this construct in simple-netaid-lightweight which avoids the >use of GtkBuilder. > >Edward Building your simple-netaid-lightweight, this is what i get: aitor@localhost:~/simple-netaid-lightweight$ make rm -f sn-lightweight gcc -Iinclude `pkg-config --libs --cflags gtk+-2.0` -c src/auxiliaries.c src/signal_functions.c src/main_gui.c src/dialog_gui.c rc/sn-lightweight.c mv *.o obj/ mv: el objetivo «obj/» no es un directorio Makefile:16: recipe for target 'compile-objs' failed make: *** [compile-objs] Error 1 So, you need to modify the Makefile to something like this: CC=gcc CFLAGS=-Iinclude GTK2FLAGS=`pkg-config --libs --cflags gtk+-2.0` D=src OBJ=obj src0=auxiliaries.c signal_functions.c main_gui.c src1=dialog_gui.c sn-lightweight.c SOURCEFILES=$(addprefix $(D)/, $(src0) $(src1)) OBJFILES=$(addprefix $(OBJ)/, $(src0:.c=.o) $(src1:.c=.o)) all: clean compile-objs sn-lightweight compile-objs: $(CC) $(CFLAGS) $(GTK2FLAGS) -c $(SOURCEFILES) mkdir obj mv *.o obj/ sn-lightweight: $(CC) $(CFLAGS) $(GTK2FLAGS) -o sn-lightweight $(OBJFILES) clean: rm -f sn-lightweight After doing this change, it works :) Cheers, Aitor. [*] Added "mkdir obj" line. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi, Again, thanks for taking some of your time to explain this to me. Sorry for not replying immediately. The past two weeks I couldn't use any of my computers. Edward On 03/04/2016, KatolaZ wrote: > On Sat, Apr 02, 2016 at 02:30:24PM -0400, Steve Litt wrote: > > [cut] > >> >> > You never return a >> > pointer to an automatic variable, >> >> How'd you learn that? I learned that by this particular incident, and I >> *NEVER* did that again. >> > > The answer to your question is always the same: I think I learnt it by > reading "The Only Book You'll Ever Need About C", alas K&R second > edition, once upon a time. > > HND > > KatolaZ > > -- > [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] > [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] > [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] > [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Sat, Apr 02, 2016 at 02:30:24PM -0400, Steve Litt wrote: [cut] > > > You never return a > > pointer to an automatic variable, > > How'd you learn that? I learned that by this particular incident, and I > *NEVER* did that again. > The answer to your question is always the same: I think I learnt it by reading "The Only Book You'll Ever Need About C", alas K&R second edition, once upon a time. HND KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Sat, 2 Apr 2016 10:55:53 +0100 KatolaZ wrote: > On Fri, Apr 01, 2016 at 07:34:02PM -0400, Steve Litt wrote: > > [cut] > > > > > > > = > > char * read_bbs(){ > > char rtrn[WAY_BIGGER_THAN_EVER_NEEDED]; > > strcpy(rtrn, grab_bbs_part1()); > > strcat(rtrn, grab_bbs_part2()); > > return(rtrn); > > } > > > > result_string = read_bbs(); > > do_other_stuff(); > > use_result_string(result_string); > > = [snip] > > Well, that one is a completely different beast... Yes it is, isn't it? :-) > You never return a > pointer to an automatic variable, How'd you learn that? I learned that by this particular incident, and I *NEVER* did that again. > unless it has been declared > "static", Yes. My "solution" was to prepend the variable declaration with the word "static", and it never crashed again. > for the simple reason that the variable does not exist any > more when the function returns. Your code probably "worked" only > because there was no call to any other functions in between (and thus > the stack was magically unmodified), but otherwise that code should in > general blow up pretty early, whatever the size of > WAY_BIGGER_THAN_EVER_NEEDED... It was a long time ago, and I don't have the code anymore, but I think what happened was that in the function returning the automatic char*, I had declared a lot of big automatic variables before the string I returned, such that subsequent functions never declared enough to reach that area of the stack, so although it was out of scope, it was left alone. However, once in a while a raly long piece of input data came through, which used up so much stack on later subroutines that the stack corresponded to the returned local pointer was overwritten, and more, and then bang, the program terminated. > Actually, returning a pointer to a local (automatic) static array is > exactly what some implementations of standard functions like "strtok" > do, and it works perfectly if you don't have multiple threads using > the same function. But you should know exactly what you are doing... Yeah, I do that alot, but I document the daylights out of the fact that if you use it twice, you need to copy away the first return. SteveT Steve Litt March 2016 featured book: Quit Joblessness: Start Your Own Business http://www.troubleshooters.com/startbiz ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
aitor_czr writes: > On 03/31/16 16:07, KatolaZ wrote: >> On Thu, Mar 31, 2016 at 03:58:49PM +0200, aitor_czr wrote: >> >> [cut] >> > >On Wed, Mar 30, 2016 at 6:04 PM, Rainer Weikusat < > >rainerweiku...@virginmedia.com> wrote: > > > >There's one > > >>important difference: > > >> > > >>char chars[] = "12345"; > > >> > > >>cause the compiler to reserve six bytes (five chars + terminating 0) > > >>in > > >>some location the program can write to. Afterwards, > > >> > > >>*chars = R; > > >> > > >>could be used to change the string to R2345. >>> > >>> >This is because >>> > >>> >*chars <---> *(chars+0) <---> chars[0] >>> > >>> >are analogous. So, chars[0] changes from 1 to R. >>> > >> Again. being pedantic here the assignment: >> >>*chars = R; >> >> assigns the value of the variable R (which should be a char) to the >> first byte of the memory area pointed by chars. Considering what it was supposed to mean, it should have been obvious that I forgot the quotes. Had R been a variable, its type could have been any numerical type as the value is to be converted as required (in fact, the type of 'R' is int, not char). Some people think this is a useful convenience feature. Others are convinced that that's a sign of tthe devil's agents being secretly at work to deprave mankind and an eternity of purgatory among dysfunctional computer must invariably ... hold a sec ... that already happened. Despite the "other's opinion" is generally accepted. Hmm ... #include char chars[] = "12345"; int main(void) { double R = 82.34; 0[chars] = R; puts(chars); return 0; } Turned into a program which can be compiled to avoid accidental syntax errors this time. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Sat, Apr 02, 2016 at 10:55:53AM +0100, KatolaZ wrote: > On Fri, Apr 01, 2016 at 07:34:02PM -0400, Steve Litt wrote: > > [cut] > > > > > > > = > > char * read_bbs(){ > > char rtrn[WAY_BIGGER_THAN_EVER_NEEDED]; > > strcpy(rtrn, grab_bbs_part1()); > > strcat(rtrn, grab_bbs_part2()); > > return(rtrn); > > } > > > > result_string = read_bbs(); > > do_other_stuff(); > > use_result_string(result_string); > > = > > > > Well, it worked 99.6% of the time, but once in a while the whole > > program blew up. :-). I solved this intermittent on my third visit, > > racked up probably 10 hours trying to fix it, and my problem probably > > cost a couple hundred hours of keypuncher time before I fixed it. > > > > WAY_BIGGER_THAN_EVER_NEEDED really was way bigger than ever needed. Bad > > programming, but that wasn't the problem. > > > > All I can say is I *never* made that mistake again. > > > > Well, that one is a completely different beast... You never return a > pointer to an automatic variable, unless it has been declared > "static", for the simple reason that the variable does not exist any > more when the function returns. Your code probably "worked" only > because there was no call to any other functions in between (and thus > the stack was magically unmodified), but otherwise that code should in > general blow up pretty early, whatever the size of > WAY_BIGGER_THAN_EVER_NEEDED... The bigger WAY_BIGGER... is the lss often it would be likely to fail. If the stack grows in the directio of lower memory addresses, the beginning of rtrn would be farther from the caller's stack position, and thus less likely to be overrun by other function calls. But it's still wrong. -- hendrik ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Fri, Apr 01, 2016 at 07:34:02PM -0400, Steve Litt wrote: [cut] > > > = > char * read_bbs(){ > char rtrn[WAY_BIGGER_THAN_EVER_NEEDED]; > strcpy(rtrn, grab_bbs_part1()); > strcat(rtrn, grab_bbs_part2()); > return(rtrn); > } > > result_string = read_bbs(); > do_other_stuff(); > use_result_string(result_string); > = > > Well, it worked 99.6% of the time, but once in a while the whole > program blew up. :-). I solved this intermittent on my third visit, > racked up probably 10 hours trying to fix it, and my problem probably > cost a couple hundred hours of keypuncher time before I fixed it. > > WAY_BIGGER_THAN_EVER_NEEDED really was way bigger than ever needed. Bad > programming, but that wasn't the problem. > > All I can say is I *never* made that mistake again. > Well, that one is a completely different beast... You never return a pointer to an automatic variable, unless it has been declared "static", for the simple reason that the variable does not exist any more when the function returns. Your code probably "worked" only because there was no call to any other functions in between (and thus the stack was magically unmodified), but otherwise that code should in general blow up pretty early, whatever the size of WAY_BIGGER_THAN_EVER_NEEDED... Actually, returning a pointer to a local (automatic) static array is exactly what some implementations of standard functions like "strtok" do, and it works perfectly if you don't have multiple threads using the same function. But you should know exactly what you are doing... My2Cents KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Thu, 31 Mar 2016 13:53:08 +0100 KatolaZ wrote: > But be careful with statically initialised strings, > since they are effectively constant char pointers (they are stored in > the current stack frame, not in the heap, and the address stored in > such variables cannot be modified, AFAIR). This isn't exactly responsive to what you said, KatolaZ, but the worst (and one of the most costly) programming mistakes I ever made was this: = char * read_bbs(){ char rtrn[WAY_BIGGER_THAN_EVER_NEEDED]; strcpy(rtrn, grab_bbs_part1()); strcat(rtrn, grab_bbs_part2()); return(rtrn); } result_string = read_bbs(); do_other_stuff(); use_result_string(result_string); = Well, it worked 99.6% of the time, but once in a while the whole program blew up. :-). I solved this intermittent on my third visit, racked up probably 10 hours trying to fix it, and my problem probably cost a couple hundred hours of keypuncher time before I fixed it. WAY_BIGGER_THAN_EVER_NEEDED really was way bigger than ever needed. Bad programming, but that wasn't the problem. All I can say is I *never* made that mistake again. SteveT Steve Litt March 2016 featured book: Quit Joblessness: Start Your Own Business http://www.troubleshooters.com/startbiz ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Thu, Mar 31, 2016 at 03:58:49PM +0200, aitor_czr wrote: > Hi, > > On 03/31/16 13:38, Emiliano Marini wrote: > >Besides, * and [] are interchangeable. You can define a string as an array > >and use it later as a pointer: > > > >char s[] = "hola"; > >char x = s[1]; // Here x = 'o' > >char y = *(s+2); // Here y = 'l' > > > >And vice versa: > > > >char *s = "hola"; > >char x = s[0]; // Here x = 'h' > >char y = *(s+3); // Here y = 'a' > > This is right, and the following sintax are analogous: > > *(p+i) <---> p[i] In fact, in the original C specification, p[i] was *defined* to mean *(p+i). -- hendrik ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Thu, Mar 31, 2016 at 03:18:17PM +0100, KatolaZ wrote: > On Thu, Mar 31, 2016 at 03:12:32PM +0200, Edward Bartolo wrote: > > Hi, thanks for taking time to reply, > > > > KatolaZ wrote: > > >> c) type **ss; // declare a pointer to pointer. System only allocates > > >> space for one address > > > > > C pointers are *always* one variable, precisely a variable large > > > enough to store a memory address on the current architecture. > > > > I think, I did not understand what you want to say. As far as I can > > imagine a pointer to pointer is something like this: > > [pointer1]-->[pointer2]--->[data] int the case of data** dt. > > > > OR > > > > [pointer1]-->[pointer2] in the case of void** ptr. > > Your example would be correct *only if* and pointer1, pointer2 actually contained proper addresses of memory instead of containing uninitialized junk or NULL. And that, I think, is what KatolaZ is tryng to point out. > > Nope. This is totally wrong. What you have in memory after a > declaration: > > type *a; > > is just *one variable*, namely a variable able to contain a memory > address. Yes. It is only when you actually assgn a pointer to a that your pointer->data diagram becomes valied. -- hendrik > When you declare: > > type **b; > > you still have exactly *one variable* allocated in memory, namely one > variable able to contain a memory address, and not *two variables* as > in your example above. This does not depend on what "type" is, so > each of the following declarations: > > int *a; > double ***b; > void c; > myowntype **d; > > will result in the allocation of exactly *one variable*, namely a > variable large enough to contain a pointer (i.e., a memory address). I > don't want to confuse you, but in my example myowntype might also be > declared as: > > typedef char*** myowntype; > > and still the declaration: > > myowntype **d; > > will reserve exactly one variable in memory, namely a variable large > enough to contain a memory address. > > The declaration is used only by the compiler to understand what is the > implicit semantic of the pointer arithmetic to be used with that > pointer, and to check that you are not palying nastly with it, so that > > int *p; > ... > p += 1; > > assigns to p the address of the memory location which is 1*sizeof(int) > bytes after the old address stored into p, while: > > double *p; > ... > p +=2; > > will assign to p the address of the memory location which is > 2*sizeof(double) bytes after the old address stored in p. > > You have not broken the pointers spell, yet. I warmly suggst you to > read a good introduction to C pointers, but the only thing that comes > to my mind is the Kernighan and Ritchie, which I admit is not the > easiest book around (although it is certainly the best on the > subject). > > My2Cents > > KatolaZ > > -- > [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] > [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] > [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] > [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Thu, Mar 31, 2016 at 03:12:32PM +0200, Edward Bartolo wrote: > Hi, thanks for taking time to reply, > > KatolaZ wrote: > >> c) type **ss; // declare a pointer to pointer. System only allocates > >> space for one address > > > C pointers are *always* one variable, precisely a variable large > > enough to store a memory address on the current architecture. > > I think, I did not understand what you want to say. As far as I can > imagine a pointer to pointer is something like this: > [pointer1]-->[pointer2]--->[data] int the case of data** dt. > > OR > > [pointer1]-->[pointer2] in the case of void** ptr. > Nope. This is totally wrong. What you have in memory after a declaration: type *a; is just *one variable*, namely a variable able to contain a memory address. When you declare: type **b; you still have exactly *one variable* allocated in memory, namely one variable able to contain a memory address, and not *two variables* as in your example above. This does not depend on what "type" is, so each of the following declarations: int *a; double ***b; void c; myowntype **d; will result in the allocation of exactly *one variable*, namely a variable large enough to contain a pointer (i.e., a memory address). I don't want to confuse you, but in my example myowntype might also be declared as: typedef char*** myowntype; and still the declaration: myowntype **d; will reserve exactly one variable in memory, namely a variable large enough to contain a memory address. The declaration is used only by the compiler to understand what is the implicit semantic of the pointer arithmetic to be used with that pointer, and to check that you are not palying nastly with it, so that int *p; ... p += 1; assigns to p the address of the memory location which is 1*sizeof(int) bytes after the old address stored into p, while: double *p; ... p +=2; will assign to p the address of the memory location which is 2*sizeof(double) bytes after the old address stored in p. You have not broken the pointers spell, yet. I warmly suggst you to read a good introduction to C pointers, but the only thing that comes to my mind is the Kernighan and Ritchie, which I admit is not the easiest book around (although it is certainly the best on the subject). My2Cents KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On 03/31/16 16:07, KatolaZ wrote: On Thu, Mar 31, 2016 at 03:58:49PM +0200, aitor_czr wrote: [cut] > >On Wed, Mar 30, 2016 at 6:04 PM, Rainer Weikusat < > >rainerweiku...@virginmedia.com> wrote: > > > >There's one > >>important difference: > >> > >>char chars[] = "12345"; > >> > >>cause the compiler to reserve six bytes (five chars + terminating 0) in > >>some location the program can write to. Afterwards, > >> > >>*chars = R; > >> > >>could be used to change the string to R2345. > >This is because > >*chars <---> *(chars+0) <---> chars[0] > >are analogous. So, chars[0] changes from 1 to R. > Again. being pedantic here the assignment: *chars = R; assigns the value of the variable R (which should be a char) to the first byte of the memory area pointed by chars. If you we want to change the first character of the string into the letter 'R', we should write: *chars = 'R'; Notice the (sometimes misleading and) subtle difference between single quotes ('), which are used for character constants, and double quotes (") which are used to delimit strings (i.e., they are the syntactic sugar around constant arrays of char). My2Cents KatolaZ Uppps :) ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Edward Bartolo: > KatolaZ wrote: > >> c) type **ss; // declare a pointer to pointer. System only allocates > >> space for one address > > > C pointers are *always* one variable, precisely a variable large > > enough to store a memory address on the current architecture. > > I think, I did not understand what you want to say. As far as I can > imagine a pointer to pointer is something like this: > [pointer1]-->[pointer2]--->[data] int the case of data** dt. ... To be picky, "int ** id;", just defines an allocates one variable id that when used like **id will have the type int. It says nothing about what value id, *id, **id will have, nor if *id or **id will be in any way useful. For **id be useful *id has to have some defined value, e.g. int main(void) { int data = 4; int * pointer1 = & data; int ** pointer2 = & pointer1; int *** pointer3 = & pointer2; int pointer4 = & pointer3; /* etc... */ return pointer4; } $ gcc -Wall a.c; ./a.out; echo $? 4 Regards, /Karl Hammar --- Aspö Data Lilla Aspö 148 S-742 94 Östhammar Sweden +46 173 140 57 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Thu, Mar 31, 2016 at 03:58:49PM +0200, aitor_czr wrote: [cut] > >On Wed, Mar 30, 2016 at 6:04 PM, Rainer Weikusat < > >rainerweiku...@virginmedia.com> wrote: > > > >There's one > >>important difference: > >> > >>char chars[] = "12345"; > >> > >>cause the compiler to reserve six bytes (five chars + terminating 0) in > >>some location the program can write to. Afterwards, > >> > >>*chars = R; > >> > >>could be used to change the string to R2345. > > This is because > > *chars <---> *(chars+0) <---> chars[0] > > are analogous. So, chars[0] changes from 1 to R. > Again. being pedantic here the assignment: *chars = R; assigns the value of the variable R (which should be a char) to the first byte of the memory area pointed by chars. If you we want to change the first character of the string into the letter 'R', we should write: *chars = 'R'; Notice the (sometimes misleading and) subtle difference between single quotes ('), which are used for character constants, and double quotes (") which are used to delimit strings (i.e., they are the syntactic sugar around constant arrays of char). My2Cents KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi, On 03/31/16 13:38, Emiliano Marini wrote: Besides, * and [] are interchangeable. You can define a string as an array and use it later as a pointer: char s[] = "hola"; char x = s[1]; // Here x = 'o' char y = *(s+2); // Here y = 'l' And vice versa: char *s = "hola"; char x = s[0]; // Here x = 'h' char y = *(s+3); // Here y = 'a' This is right, and the following sintax are analogous: *(p+i) <---> p[i] *(*(p+i)+j) <---> p[i][j] This last one in the case of a double pointer. On Wed, Mar 30, 2016 at 6:04 PM, Rainer Weikusat < rainerweiku...@virginmedia.com> wrote: There's one >important difference: > >char chars[] = "12345"; > >cause the compiler to reserve six bytes (five chars + terminating 0) in >some location the program can write to. Afterwards, > >*chars = R; > >could be used to change the string to R2345. This is because *chars <---> *(chars+0) <---> chars[0] are analogous. So, chars[0] changes from 1 to R. Aitor. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi, thanks for taking time to reply, KatolaZ wrote: >> c) type **ss; // declare a pointer to pointer. System only allocates >> space for one address > C pointers are *always* one variable, precisely a variable large > enough to store a memory address on the current architecture. I think, I did not understand what you want to say. As far as I can imagine a pointer to pointer is something like this: [pointer1]-->[pointer2]--->[data] int the case of data** dt. OR [pointer1]-->[pointer2] in the case of void** ptr. Edward On 31/03/2016, KatolaZ wrote: > On Thu, Mar 31, 2016 at 08:38:26AM -0300, Emiliano Marini wrote: >> +1 >> >> Besides, * and [] are interchangeable. You can define a string as an array >> and use it later as a pointer: >> >> char s[] = "hola"; >> char x = s[1]; // Here x = 'o' >> char y = *(s+2); // Here y = 'l' >> >> And vice versa: >> >> char *s = "hola"; >> char x = s[0]; // Here x = 'h' >> char y = *(s+3); // Here y = 'a' >> > > Just to be pedantic here, "[]" is just syntactic sugar around the > dereference operator "*". And in fact "[]" did not even exist in the > first versions of proto-C. Obviously, "[]" is syntactic sugar around > unary "*" for *any* kind of pointer, not just for strings. > > Also, initialisation of char* and char[] by means of > > char s[] = "hello"; > > is syntactic sugar around the generic initialiser: > > type p = {...}; > > which allows to initialise arrays and compound variables (structs and > unions) as well. But be careful with statically initialised strings, > since they are effectively constant char pointers (they are stored in > the current stack frame, not in the heap, and the address stored in > such variables cannot be modified, AFAIR). > > My2Cents > > KatolaZ > > -- > [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] > [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] > [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] > [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Thu, Mar 31, 2016 at 08:38:26AM -0300, Emiliano Marini wrote: > +1 > > Besides, * and [] are interchangeable. You can define a string as an array > and use it later as a pointer: > > char s[] = "hola"; > char x = s[1]; // Here x = 'o' > char y = *(s+2); // Here y = 'l' > > And vice versa: > > char *s = "hola"; > char x = s[0]; // Here x = 'h' > char y = *(s+3); // Here y = 'a' > Just to be pedantic here, "[]" is just syntactic sugar around the dereference operator "*". And in fact "[]" did not even exist in the first versions of proto-C. Obviously, "[]" is syntactic sugar around unary "*" for *any* kind of pointer, not just for strings. Also, initialisation of char* and char[] by means of char s[] = "hello"; is syntactic sugar around the generic initialiser: type p = {...}; which allows to initialise arrays and compound variables (structs and unions) as well. But be careful with statically initialised strings, since they are effectively constant char pointers (they are stored in the current stack frame, not in the heap, and the address stored in such variables cannot be modified, AFAIR). My2Cents KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Thu, Mar 31, 2016 at 08:38:26AM -0300, Emiliano Marini wrote: > +1 > > Besides, * and [] are interchangeable. You can define a string as an array > and use it later as a pointer: > > char s[] = "hola"; > char x = s[1]; // Here x = 'o' > char y = *(s+2); // Here y = 'l' > > And vice versa: > > char *s = "hola"; > char x = s[0]; // Here x = 'h' > char y = *(s+3); // Here y = 'a' Bit sizeof(s) will not be the sae iin the two versions. -- hendrik ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Wed, Mar 30, 2016 at 10:40:37PM +0200, Edward Bartolo wrote: > Hi, thanks for your help. > > So: [ I am recalling this from memory to test where I am ] > a) type* pp; // declare a pointer pp > b) *pp = RHS; // assign RHS to the data pointed to by pp This is a bit fishy, and should be taken with care. In a word, you should be very careful about what is in the RHS, and you should be sure that whatever is on the RHS "fits" in the memory area starting at the location stored into pp. > c) type **ss; // declare a pointer to pointer. System only allocates > space for one address C pointers are *always* one variable, precisely a variable large enough to store a memory address on the current architecture. > d) *ss = RHS; // assign RHS to the pointer pointed to by ss. This is no different from b) above, is it? > e) const char* and char* are not the same ie treated differently by the > compiler "const" is a qualifier that modifies what you can do with a pointer. If a pointer is declared "const" (usually in the signature of a function), then any assignment that directly tries to change the value of that pointer should be forbidden at compile time. I say "should" because some compilers simply ignore the "const" qualifier. > f) strings are character arrays, so they obey the rules governing arrays Definitely. A string is just an array of char, and the variable you use to handle strings is a char*. The usual pointer arithmetics holds for any kind of pointer, including char*. > g) strings are terminated by a null character which is a byte with eight zeros This only makes sense if you want to use the standard functions to handle strings. Nothing forbids you for creating and handling by your own an array or chars (identified by a char*) which is not null-terminated. > h) extra care must be taken when copying strings not to write beyond > the end of allocated memory. This can result in buffer overflows that > may cause execution of arbitrary code Extra care should be taken when copying between *any* two memory areas, and strings are not an exception. > i) some built in string function provided by C, especially vintage > string functions, suffer from the buffer overrun bug. Guard against > that by making sure there is enough memory allocated. > j) When calling backend CLI programs make sure, the input to the > calling function cannot be maliciously modified to allow execution of > arbitrary commands. Functions like execl can be abused so extra care > to block abuse must be taken. This is generally true, but has nothing much to do with the previous points. My2Cents KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
+1 Besides, * and [] are interchangeable. You can define a string as an array and use it later as a pointer: char s[] = "hola"; char x = s[1]; // Here x = 'o' char y = *(s+2); // Here y = 'l' And vice versa: char *s = "hola"; char x = s[0]; // Here x = 'h' char y = *(s+3); // Here y = 'a' On Wed, Mar 30, 2016 at 6:04 PM, Rainer Weikusat < rainerweiku...@virginmedia.com> wrote: > Edward Bartolo writes: > > > Hi, thanks for your help. > > > > So: [ I am recalling this from memory to test where I am ] > > a) type* pp; // declare a pointer pp > > b) *pp = RHS; // assign RHS to the data pointed to by pp > > c) type **ss; // declare a pointer to pointer. System only allocates > > space for one address > > (1) Background > -- > > The C type system is built around the idea that certain kind of types can > be > derived from already existing types. These are pointers, arrays (and > functions, but I'm going to omit them for simplicity). Eg, assuming type > identifies and existing type, > > type *pt > > declares a pointer to objects of type type and > > type at[3]; > > declares an array of objects of type type. When an object is defined, > the system allocates storage for it in some suitable location, eg, on > the stack or by reserving a register. > > (2)Typedef names > > > It's possible to create a new name for an existing type with the help of > typedef, eg, after > > typedef int *pint; > > pint can be used as type name to mean 'pointer to int'. Eg, > > pint pi; > > would define an object of type 'pointer to int' (the compiler will > allocate storage for). > > Pulling this together > - > > Assuming pint is declared as above. As per (1), new types can now > derived from it, eg, > > pint *ppi; /* "Dear customer ..." */ > > This defines a "pointer to pint", hence, the system allocates storage > for one. But that's really the same as > > int **ppi; > > which is handled in exactly the same way: An object with a pointer type > derived from some existing type is defined. Hence, storage for a pointer > is reserved. That the existing type is itself a pointer type doesn't > matter, for the given purpose, it's just 'some type'. > > > > f) strings are character arrays, so they obey the rules governing arrays > > They're really pointers to character arrays. Because an array is > converted to a pointer to its first element most of the time, a > character array, say > > char chars[] = "12345"; > > can be used as if it had been declared as a pointer. There's one > important difference: > > char chars[] = "12345"; > > cause the compiler to reserve six bytes (five chars + terminating 0) in > some location the program can write to. Afterwards, > > *chars = R; > > could be used to change the string to R2345. In contrast to this. > > char *chars = "12345"; > > causes the compiler to allocate storage for a writable char * and > initialize that with the address of a string literal which is not > required to be (and usually won't be) writeable. > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Exactly, any local variable comes off the stack, but I was talking about pointers :) On Wed, Mar 30, 2016 at 3:37 PM, Steve Litt wrote: > On Wed, 30 Mar 2016 08:23:16 -0300 > Emiliano Marini wrote: > > > Edward, the only time the compiler allocates memory for data > > automatically is when using strings literals (as stated by Rainer > > previously) > > > > char *p = "Hola mundo." > > Also when you have a struct as a local variable: > > struct my_cool_struct mystruct; > > Like the char pointer, it comes off the stack, not the heap it would > come off if you used malloc(). > > Actually, any local variable allocates memory off the stack. Consider: > > int number_of_people; > > The preceding allocates sizeof(int) bytes, for number_of_people, off > the stack. > > SteveT > > Steve Litt > March 2016 featured book: Quit Joblessness: Start Your Own Business > http://www.troubleshooters.com/startbiz > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On 2016-03-28 06:50:38 +, Edward Bartolo said: Hi, As the title of the email indicates, I am doing some exercises to make sense out of C pointer syntax. I have been using pointers for as long as I have been programming without issues, apart from the usual initial programmatic errors when new code is run for the first time. However, C pointer syntax is proving to be as unintuitive as it can be. For this reason, I am doing some exercises regarding C pointer use. I am attaching two short C programs that I created and which I tested to work although the mechanism by which they work is still somewhat hazy to me. Both programs use a function to change the value of a parameter. I want to understand, as opposed to knowing by rote, the mechanism why they work. Please note that I didn't consult any books to create the pointers. This is because I have already the concepts, but I cannot make sense, as in deeply understanding the details, of pointer syntax as used in C. Edward ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng Hi, If you read the Usenet time Comp Lang C FAQ by Steve Summit you will find many answers and learn a lot about the C language. This helped me plenty coming from many asm languages. https://www.eskimo.com/~scs/___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Edward Bartolo writes: > Hi, thanks for your help. > > So: [ I am recalling this from memory to test where I am ] > a) type* pp; // declare a pointer pp > b) *pp = RHS; // assign RHS to the data pointed to by pp > c) type **ss; // declare a pointer to pointer. System only allocates > space for one address (1) Background -- The C type system is built around the idea that certain kind of types can be derived from already existing types. These are pointers, arrays (and functions, but I'm going to omit them for simplicity). Eg, assuming type identifies and existing type, type *pt declares a pointer to objects of type type and type at[3]; declares an array of objects of type type. When an object is defined, the system allocates storage for it in some suitable location, eg, on the stack or by reserving a register. (2)Typedef names It's possible to create a new name for an existing type with the help of typedef, eg, after typedef int *pint; pint can be used as type name to mean 'pointer to int'. Eg, pint pi; would define an object of type 'pointer to int' (the compiler will allocate storage for). Pulling this together - Assuming pint is declared as above. As per (1), new types can now derived from it, eg, pint *ppi; /* "Dear customer ..." */ This defines a "pointer to pint", hence, the system allocates storage for one. But that's really the same as int **ppi; which is handled in exactly the same way: An object with a pointer type derived from some existing type is defined. Hence, storage for a pointer is reserved. That the existing type is itself a pointer type doesn't matter, for the given purpose, it's just 'some type'. > f) strings are character arrays, so they obey the rules governing arrays They're really pointers to character arrays. Because an array is converted to a pointer to its first element most of the time, a character array, say char chars[] = "12345"; can be used as if it had been declared as a pointer. There's one important difference: char chars[] = "12345"; cause the compiler to reserve six bytes (five chars + terminating 0) in some location the program can write to. Afterwards, *chars = R; could be used to change the string to R2345. In contrast to this. char *chars = "12345"; causes the compiler to allocate storage for a writable char * and initialize that with the address of a string literal which is not required to be (and usually won't be) writeable. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi, thanks for your help. So: [ I am recalling this from memory to test where I am ] a) type* pp; // declare a pointer pp b) *pp = RHS; // assign RHS to the data pointed to by pp c) type **ss; // declare a pointer to pointer. System only allocates space for one address d) *ss = RHS; // assign RHS to the pointer pointed to by ss. e) const char* and char* are not the same ie treated differently by the compiler f) strings are character arrays, so they obey the rules governing arrays g) strings are terminated by a null character which is a byte with eight zeros h) extra care must be taken when copying strings not to write beyond the end of allocated memory. This can result in buffer overflows that may cause execution of arbitrary code i) some built in string function provided by C, especially vintage string functions, suffer from the buffer overrun bug. Guard against that by making sure there is enough memory allocated. j) When calling backend CLI programs make sure, the input to the calling function cannot be maliciously modified to allow execution of arbitrary commands. Functions like execl can be abused so extra care to block abuse must be taken. Edward On 30/03/2016, Steve Litt wrote: > On Wed, 30 Mar 2016 08:23:16 -0300 > Emiliano Marini wrote: > >> Edward, the only time the compiler allocates memory for data >> automatically is when using strings literals (as stated by Rainer >> previously) >> >> char *p = "Hola mundo." > > Also when you have a struct as a local variable: > > struct my_cool_struct mystruct; > > Like the char pointer, it comes off the stack, not the heap it would > come off if you used malloc(). > > Actually, any local variable allocates memory off the stack. Consider: > > int number_of_people; > > The preceding allocates sizeof(int) bytes, for number_of_people, off > the stack. > > SteveT > > Steve Litt > March 2016 featured book: Quit Joblessness: Start Your Own Business > http://www.troubleshooters.com/startbiz > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Wed, 30 Mar 2016 08:23:16 -0300 Emiliano Marini wrote: > Edward, the only time the compiler allocates memory for data > automatically is when using strings literals (as stated by Rainer > previously) > > char *p = "Hola mundo." Also when you have a struct as a local variable: struct my_cool_struct mystruct; Like the char pointer, it comes off the stack, not the heap it would come off if you used malloc(). Actually, any local variable allocates memory off the stack. Consider: int number_of_people; The preceding allocates sizeof(int) bytes, for number_of_people, off the stack. SteveT Steve Litt March 2016 featured book: Quit Joblessness: Start Your Own Business http://www.troubleshooters.com/startbiz ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Wed, Mar 30, 2016 at 09:16:22AM +0200, Edward Bartolo wrote: > Hi and many thanks for the replies, > > I can understand that a pointer being an address depends heavily on > machine architecture which means, on 32 bit machines it is 4 bytes > long and on 64 bit machines it is 8 bytes long. I also understand that > a pointer variable is essentially made of two parts as illustrated > below: > > address [always allocated] --> data [not allocated > automatically] > > The address does depend on architecture but the data? And what else > can enter into a pointer's definition other than what I illustrated? Some machines (I'm thinking of, say, the PDP-10, which had a 36-bit wors soze, and, if I remember correctly, eighteen-bit addresses) found that it was good to stuff many characters into a single addressible machine word. I think the PDP-10 stuffed five seven-bit characters into a word, leaving the sign bit unmolested. But sometime it was necessary to address intividual characters within a word. To this eend, they made special character pointers, which were a few bits longer than a regular address. So character pointers were not the same size as regular pointers. There are have also been systems where a function pointer has two compononts -- the address of the code to be executed and the address of the environment the function is to operate in. There are historical reasos for that (mostly having to do with programming language that are not C), but on machines designed for that, function pointers will be bigger than data pointers. But C is part of the legacy of 8-bit bytes and byte-addressable machines. -- hendrik ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Edward, the only time the compiler allocates memory for data automatically is when using strings literals (as stated by Rainer previously) char *p = "Hola mundo." This is because strings are a special case. https://www.cs.uic.edu/~jbell/CourseNotes/C_Programming/CharacterStrings.html On Wed, Mar 30, 2016 at 4:16 AM, Edward Bartolo wrote: > Hi and many thanks for the replies, > > I can understand that a pointer being an address depends heavily on > machine architecture which means, on 32 bit machines it is 4 bytes > long and on 64 bit machines it is 8 bytes long. I also understand that > a pointer variable is essentially made of two parts as illustrated > below: > > address [always allocated] --> data [not allocated > automatically] > > The address does depend on architecture but the data? And what else > can enter into a pointer's definition other than what I illustrated? > > Compound/complex pointer definitions like data_type** U, work as > follows as far as my intellect can reason and deduce from what I > studied and from my now long experience coding. > > address1[allocated] -> address2[NOT allocated] -> > data_type[not allocated] > > My mistake was to assume in the case of data_type** U the compiler > would allocate the two addresses and link them, that is, store the > address of address2 in address1. The latter is not the case and a > coder is required to first allocate space for the 2nd address. In > fact, allocating space for void** ptr, in a sample program worked > without issues. I am attaching this sample program. > > Edward > > On 29/03/2016, Rainer Weikusat wrote: > > Hendrik Boom writes: > >> On Tue, Mar 29, 2016 at 02:46:50PM +0100, Rainer Weikusat wrote: > >>> This is a wrong assumption and it relies on behaviour the C standard > >>> doesn't guarantee. Any pointer may be converted (it's even converted > >>> automatically as required) to a void * and back and > >>> > >>> "the result shall compare equal to the original pointer" > >>> > >>> But a pointer to a void * is an entirely different animal and no such > >>> guarantees are made for that. This will work in practice if there's > only > >>> one 'machine pointer type' anyway, though. But using it is not > necessary > >>> as void * is sufficient. > >> > >> Last time I looked at the C standard (which was a while ago, things may > >> have changed) function pointers were not guaranteed to be > >> interconvertable with data pointers. > > > > Indeed. I didn't remember this while writing the text. > > ___ > > Dng mailing list > > Dng@lists.dyne.org > > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > > > > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
+1 On Wed, Mar 30, 2016 at 5:04 AM, KatolaZ wrote: > On Wed, Mar 30, 2016 at 09:16:22AM +0200, Edward Bartolo wrote: > > Hi and many thanks for the replies, > > > > I can understand that a pointer being an address depends heavily on > > machine architecture which means, on 32 bit machines it is 4 bytes > > long and on 64 bit machines it is 8 bytes long. I also understand that > > a pointer variable is essentially made of two parts as illustrated > > below: > > > > address [always allocated] --> data [not allocated > > automatically] > > > > The address does depend on architecture but the data? And what else > > can enter into a pointer's definition other than what I illustrated? > > > > Hi Edward, > > sorry but your description is incorrect. A pointer in C is just a > variable large enough to contain a memory address. Period. There is no > explicit or implicit linking between a pointer (which is a variable > large enough to contain a memory address) and the area of memory it > points to. You may have several pointers pointing to the same memory > area. You can have the same pointer (i.e., the same named variable > able to contain a memory address) pointing to different memory areas > at different times. You can use a pointer to wander around an > allocated memory area at your will, changing its value by using the > powerful pointer arithmetic provided by C. You can also have some > allocated memory area for which you don't have any pointer at all (and > this is what is called a "memory leak", and you should avoid it). > > Also, memory areas are not "typed" in C, meaning that you can in > principle access a correctly allocated memory area with pointers of > any type, the only problem being the semantics of pointer arithmetics, > which is entirely left to the programmer. > > But please forget any implicit linkage between a pointer (the > variable) and the memory area it points to (i.e., the address > contained in that variable), as you don't assume any intrinsic link > between an integer variable and the possible values that the variable > can contain. If you don't break this spell, you will never get around > with C pointers. > > Pointers are just variables which are able to contain memory > addresses. What you put in those variables does not bother them in any > discernible way. And shouldn't bother you either, as long as you be > careful in using them to refer to correctly allocated memory. SIGSEGV > is the alternative. > > My2Cents > > KatolaZ > > -- > [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] > [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] > [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] > [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Wed, Mar 30, 2016 at 09:26:32AM +0200, Edward Bartolo wrote: > Hi, > > I can also understand that typecasting, that is, bypassing strict type > checking, a void pointer without checking for architecture is like a > time bomb. Addresses on different architectures can be different sizes > and a typecast of void from an integer requires some conditions that > must be true. Both void* and integer must have the same size on the > target machine or code is written in a way to make sure a difference > in architecture does not result in code being broken. > void* and int happen to have the same size in i386 architectures, but this is not always true. There is no implied correspondence between void* and int that I am aware of. In my amd64 machine, all pointers are 8 bytes, but an int is 4 bytes long. Please do not make assumptions about the length of a pointer. The typecasting referred before was *between pointers*, and not between pointers and other types. This means that you can cast a void* to a char* or to an int**, but not that you can cast a void* to a char. Also, pointer arithmetic is defined (to the best of my knowledge) only on typed pointers, so that something like: void *a; a = a +1; is not meaningful (and I bet you should get a compile-time error), while: void *a; a = (int*) a + 1; is perfectly valid, and widely used. My2Cents KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Wed, Mar 30, 2016 at 09:16:22AM +0200, Edward Bartolo wrote: > Hi and many thanks for the replies, > > I can understand that a pointer being an address depends heavily on > machine architecture which means, on 32 bit machines it is 4 bytes > long and on 64 bit machines it is 8 bytes long. I also understand that > a pointer variable is essentially made of two parts as illustrated > below: > > address [always allocated] --> data [not allocated > automatically] > > The address does depend on architecture but the data? And what else > can enter into a pointer's definition other than what I illustrated? > Hi Edward, sorry but your description is incorrect. A pointer in C is just a variable large enough to contain a memory address. Period. There is no explicit or implicit linking between a pointer (which is a variable large enough to contain a memory address) and the area of memory it points to. You may have several pointers pointing to the same memory area. You can have the same pointer (i.e., the same named variable able to contain a memory address) pointing to different memory areas at different times. You can use a pointer to wander around an allocated memory area at your will, changing its value by using the powerful pointer arithmetic provided by C. You can also have some allocated memory area for which you don't have any pointer at all (and this is what is called a "memory leak", and you should avoid it). Also, memory areas are not "typed" in C, meaning that you can in principle access a correctly allocated memory area with pointers of any type, the only problem being the semantics of pointer arithmetics, which is entirely left to the programmer. But please forget any implicit linkage between a pointer (the variable) and the memory area it points to (i.e., the address contained in that variable), as you don't assume any intrinsic link between an integer variable and the possible values that the variable can contain. If you don't break this spell, you will never get around with C pointers. Pointers are just variables which are able to contain memory addresses. What you put in those variables does not bother them in any discernible way. And shouldn't bother you either, as long as you be careful in using them to refer to correctly allocated memory. SIGSEGV is the alternative. My2Cents KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi, I can also understand that typecasting, that is, bypassing strict type checking, a void pointer without checking for architecture is like a time bomb. Addresses on different architectures can be different sizes and a typecast of void from an integer requires some conditions that must be true. Both void* and integer must have the same size on the target machine or code is written in a way to make sure a difference in architecture does not result in code being broken. Edward On 30/03/2016, Edward Bartolo wrote: > Hi and many thanks for the replies, > > I can understand that a pointer being an address depends heavily on > machine architecture which means, on 32 bit machines it is 4 bytes > long and on 64 bit machines it is 8 bytes long. I also understand that > a pointer variable is essentially made of two parts as illustrated > below: > > address [always allocated] --> data [not allocated > automatically] > > The address does depend on architecture but the data? And what else > can enter into a pointer's definition other than what I illustrated? > > Compound/complex pointer definitions like data_type** U, work as > follows as far as my intellect can reason and deduce from what I > studied and from my now long experience coding. > > address1[allocated] -> address2[NOT allocated] -> > data_type[not allocated] > > My mistake was to assume in the case of data_type** U the compiler > would allocate the two addresses and link them, that is, store the > address of address2 in address1. The latter is not the case and a > coder is required to first allocate space for the 2nd address. In > fact, allocating space for void** ptr, in a sample program worked > without issues. I am attaching this sample program. > > Edward > > On 29/03/2016, Rainer Weikusat wrote: >> Hendrik Boom writes: >>> On Tue, Mar 29, 2016 at 02:46:50PM +0100, Rainer Weikusat wrote: This is a wrong assumption and it relies on behaviour the C standard doesn't guarantee. Any pointer may be converted (it's even converted automatically as required) to a void * and back and "the result shall compare equal to the original pointer" But a pointer to a void * is an entirely different animal and no such guarantees are made for that. This will work in practice if there's only one 'machine pointer type' anyway, though. But using it is not necessary as void * is sufficient. >>> >>> Last time I looked at the C standard (which was a while ago, things may >>> have changed) function pointers were not guaranteed to be >>> interconvertable with data pointers. >> >> Indeed. I didn't remember this while writing the text. >> ___ >> Dng mailing list >> Dng@lists.dyne.org >> https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng >> > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi and many thanks for the replies, I can understand that a pointer being an address depends heavily on machine architecture which means, on 32 bit machines it is 4 bytes long and on 64 bit machines it is 8 bytes long. I also understand that a pointer variable is essentially made of two parts as illustrated below: address [always allocated] --> data [not allocated automatically] The address does depend on architecture but the data? And what else can enter into a pointer's definition other than what I illustrated? Compound/complex pointer definitions like data_type** U, work as follows as far as my intellect can reason and deduce from what I studied and from my now long experience coding. address1[allocated] -> address2[NOT allocated] -> data_type[not allocated] My mistake was to assume in the case of data_type** U the compiler would allocate the two addresses and link them, that is, store the address of address2 in address1. The latter is not the case and a coder is required to first allocate space for the 2nd address. In fact, allocating space for void** ptr, in a sample program worked without issues. I am attaching this sample program. Edward On 29/03/2016, Rainer Weikusat wrote: > Hendrik Boom writes: >> On Tue, Mar 29, 2016 at 02:46:50PM +0100, Rainer Weikusat wrote: >>> This is a wrong assumption and it relies on behaviour the C standard >>> doesn't guarantee. Any pointer may be converted (it's even converted >>> automatically as required) to a void * and back and >>> >>> "the result shall compare equal to the original pointer" >>> >>> But a pointer to a void * is an entirely different animal and no such >>> guarantees are made for that. This will work in practice if there's only >>> one 'machine pointer type' anyway, though. But using it is not necessary >>> as void * is sufficient. >> >> Last time I looked at the C standard (which was a while ago, things may >> have changed) function pointers were not guaranteed to be >> interconvertable with data pointers. > > Indeed. I didn't remember this while writing the text. > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > #include #include typedef enum {t_int, t_float, t_double, t_long_double} t_data; int alloc_datum(void** datum, t_data type) { //if (*datum != NULL) return 2; // non null *datum switch (type) { case t_int: *datum = malloc(sizeof(int)); break; case t_float: *datum = malloc(sizeof(float)); break; case t_double: *datum = malloc(sizeof(double)); break; case t_long_double: *datum = malloc(sizeof(long double)); break; } if (datum == NULL) return 1; // malloc failed to allocate memory else return 0; } int main() { int* ii; long* ll; float* ff; double* dd; long double* ; void** ptr; ptr = malloc(sizeof(void*)); alloc_datum(ptr, t_int); ii = *ptr; *ii = 10; alloc_datum(ptr, t_float); ff = *ptr; *ff = 5.97E24; alloc_datum(ptr, t_double); dd = *ptr; *dd = 2E30; alloc_datum(ptr, t_long_double); = *ptr; * = 1.5E299; free(ptr); printf("*11 is %d\n", *ii); printf("*ff is %e\n", *ff); printf("*dd is %e\n", *dd); printf("* is %Le\n", *); free(ii); free(ff); free(dd); free(); return 0; }___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hendrik Boom writes: > On Tue, Mar 29, 2016 at 02:46:50PM +0100, Rainer Weikusat wrote: >> This is a wrong assumption and it relies on behaviour the C standard >> doesn't guarantee. Any pointer may be converted (it's even converted >> automatically as required) to a void * and back and >> >> "the result shall compare equal to the original pointer" >> >> But a pointer to a void * is an entirely different animal and no such >> guarantees are made for that. This will work in practice if there's only >> one 'machine pointer type' anyway, though. But using it is not necessary >> as void * is sufficient. > > Last time I looked at the C standard (which was a while ago, things may > have changed) function pointers were not guaranteed to be > interconvertable with data pointers. Indeed. I didn't remember this while writing the text. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Tue, Mar 29, 2016 at 02:46:50PM +0100, Rainer Weikusat wrote: > This is a wrong assumption and it relies on behaviour the C standard > doesn't guarantee. Any pointer may be converted (it's even converted > automatically as required) to a void * and back and > > "the result shall compare equal to the original pointer" > > But a pointer to a void * is an entirely different animal and no such > guarantees are made for that. This will work in practice if there's only > one 'machine pointer type' anyway, though. But using it is not necessary > as void * is sufficient. Last time I looked at the C standard (which was a while ago, things may have changed) function pointers were not guaranteed to be interconvertable with data pointers. You could cast them back and forth, but there was no guarantee they would survive the round trip. -- hendrik ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi Edward, On 03/29/16 16:34, Edward Bartolo wrote: Is this allowed: void***, int***, double***, etc? Yes, this is allowed. Imagine them like the tensors in algebra: there is no limitation in the number of indices. Aitor. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Steve Litt writes: > On Mon, 28 Mar 2016 13:57:08 -0300 > Emiliano Marini wrote: > >> char *p; >> p="01234"; /* skeezy, but makes the point */ >> >> Warning! Here "p" is pointing to nowhere, you don't know which memory >> locations are writing to. > > Yeah, that's why I said "skeezy". But on some of compilers, you can > actually strcpy(p, "43210") and you will neither get a compile time > error nor a runtime one, because when p is in scope, it points to 6 > bytes *somewhere*, even if on the stack. That's not necessarily true. Eg, on a 64-bit Intel machine using gcc 4.7.2, this program static long long *llp(void) { long long x; x = -2; return &x; } static void *ouch(void) { char *p; *p = 3; return &p; } int main(void) { llp(); ouch(); return 0; } will segfault because the pointer gets the value assigned to the long long used earlier. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Edward Bartolo writes: > Hi, > > Thanks for dedicating some of your time to answer me. I used: > > void change_value(void** ptr) > > Because I wanted to enable myself to allocate memory for the pointer > inside the function, therefore I needed a pointer to a pointer of type > void. This is a wrong assumption and it relies on behaviour the C standard doesn't guarantee. Any pointer may be converted (it's even converted automatically as required) to a void * and back and "the result shall compare equal to the original pointer" But a pointer to a void * is an entirely different animal and no such guarantees are made for that. This will work in practice if there's only one 'machine pointer type' anyway, though. But using it is not necessary as void * is sufficient. #include #include enum { CHAR = 1, SHORT = sizeof(short), INT = sizeof(int), LLONG = sizeof(long long) }; static void alloc_int(void *p, int which) { void *area; area = malloc(which); switch (which) { case CHAR: *(char **)p = area; break; case SHORT: *(short **)p = area; break; case INT: *(int **)p = area; break; case LLONG: *(long long **)p = area; } } int main(void) { unsigned long long *pll; alloc_int(&pll, LLONG); *pll = -1; printf("%llx\n", *pll); return 0; } NB: That's seriously bizarre code. [...] > This is a program employing the use of a pointer to change the value > of a parameter inside a function. > > #include > #include > > int afunc(double* dd) { > *dd *= 2; > } There's a return statement missing here or the declared return value is wrong. It's a good idea to enable compiler warnings when compiling as this means the compiler will - well - warn about such issues: [rw@doppelsaurus]/tmp#gcc -W -Wall b.c b.c: In function 'afunc': b.c:6:1: warning: control reaches end of non-void function [-Wreturn-type] Also, to state this again: C is not Pascal and doesn't distinguish between 'subprograms which may return values and should/ must not have side effects' (function) and 'subprograms which are executed for the side effects but cannot return values except by using output parameters'. When you're writing C, use the return value to return values, eg double afunc(double in) { return in * 2; } [...] > The reason for this is the fact that a pointer is a number. A machine address may be a number but a pointer isn't. That's something abstract defined by C as having certain properties. Among these are that pointers may be converted to integers and vice versa but the effect is implementation dependent and the behaviour may be undefined. Again, provided the integer has a sufficient size, this will usually work. There are also optional types intptr_t and uintptr_t guaranteed to be capable of storing the value of a void *. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
This is correct: int **L ===> Address1(preallocated) -> Address2(not allocated) -> > int (not allocated) > When you declare a variable, the compiler will reserve memory space to store it. No matter how may asterisks a variable has, from the compiler's view it's only a memory address. So it will reserve space to store an address: int *x; x will store a memory address, so the compiler has to reserve 8 bytes (amd64) for it. Conclusion: the size of a pointer will be always the same, no matter what is pointing to (an integer, a char, an address...) On Tue, Mar 29, 2016 at 9:00 AM, Edward Bartolo wrote: > Hi, > > As far as I know, the compiler automatically allocates memory for the > address where a pointer is saved. The unallocated part is the data > attached to a pointer. What happens with a pointer to a pointer like > void**? Does the compiler allocate memory for two addresses with the > first one in the chain pointing to the second one? Does it allocate > memory only for the first address? > > What I can say about pointers: > > a) int * K ===>Address(preallocated) ---> integer > [ not preallocated ] > > b) void** V ===> Address1 (preallocated) --> Address2(preallocated) > > OR: > > void** V ===> Address1 (preallocated) -> Address2(not preallocated) > > ? > > c) int **L ===> Address1 (preallocated) -> Address2(allocated) > -> int (not allocated) > > OR > > int **L ===> Address1(preallocated) -> Address2(not allocated) > -> int (not allocated) > > By 'preallocated' I mean the compiler will automatically generate code > to allocate memory for the actual pointer not the data. > > d) Is this allowed: void***, int***, double***, etc? > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi, As far as I know, the compiler automatically allocates memory for the address where a pointer is saved. The unallocated part is the data attached to a pointer. What happens with a pointer to a pointer like void**? Does the compiler allocate memory for two addresses with the first one in the chain pointing to the second one? Does it allocate memory only for the first address? What I can say about pointers: a) int * K ===>Address(preallocated) ---> integer [ not preallocated ] b) void** V ===> Address1 (preallocated) --> Address2(preallocated) OR: void** V ===> Address1 (preallocated) -> Address2(not preallocated) ? c) int **L ===> Address1 (preallocated) -> Address2(allocated) -> int (not allocated) OR int **L ===> Address1(preallocated) -> Address2(not allocated) -> int (not allocated) By 'preallocated' I mean the compiler will automatically generate code to allocate memory for the actual pointer not the data. d) Is this allowed: void***, int***, double***, etc? ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Le 29/03/2016 10:30, Edward Bartolo a écrit : Sometimes, a generic pointer is very useful. For instance, the Windows API documents functions that have untyped pointers. These allow great flexibility and behave like the variant type in other languages but with efficient memory consumption. Delphi Pascal has both the variant and untyped pointer types. This clearly shows there are advantages to having the possibility of using untyped pointers. The Windows API CreateProcess function is such an example. Using pointers to untyped arguments is loose programming. It is like removing the handrail of your balcony to unhide the view. It gives good looking code which is easier to write and read but deadly error-prone. This is definitely non-professional. In case it's really worth the pain, you can use polymorphic variables in C: a struct containing a discriminant and a union, the discriminant indicating which member of the union to use. The actual implementation of an object is probably not different of this, with the difference that the compiler and the run-time library perform the discrimination and checking for you, which is safer of course. Didier ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi, Sometimes, a generic pointer is very useful. For instance, the Windows API documents functions that have untyped pointers. These allow great flexibility and behave like the variant type in other languages but with efficient memory consumption. Delphi Pascal has both the variant and untyped pointer types. This clearly shows there are advantages to having the possibility of using untyped pointers. The Windows API CreateProcess function is such an example. Edward ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Mon, Mar 28, 2016 at 09:55:08PM +0200, Edward Bartolo wrote: > Hi, > > Thanks for dedicating some of your time to answer me. I used: > > void change_value(void** ptr) > > Because I wanted to enable myself to allocate memory for the pointer > inside the function, therefore I needed a pointer to a pointer of type > void. Void allows such a function to handle different data types in > which case an ordinal typed parameter may be used to allow a switch > statement within the function to handle the different data types. I > used such a construct in Delphi Pascal in the past, and consider it a > powerful feature that can have its uses. This is why I am anxious to > comprehend the why behind pointer to pointer use. > Allocating memory for a generic variable into a function is seldom of any use, since you need to specify how much memory (number of bytes) your function should allocate anyway. Although it is still possible to code such a function, I think it is in general a bad idea. Why don't you use malloc directly for this purpose? Producing good-quality and maintanable software is also about providing clean interfaces to the user, and by "interface" I mean function signatures, which should be self-explanatory and clear. If I can get almost anything as a result value of a function call, then that function is likely to become a can of worms... My2Cents KatolaZ -- [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ] [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ] [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ] [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ] ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Mon, 28 Mar 2016 13:57:08 -0300 Emiliano Marini wrote: > char *p; > p="01234"; /* skeezy, but makes the point */ > > Warning! Here "p" is pointing to nowhere, you don't know which memory > locations are writing to. Yeah, that's why I said "skeezy". But on some of compilers, you can actually strcpy(p, "43210") and you will neither get a compile time error nor a runtime one, because when p is in scope, it points to 6 bytes *somewhere*, even if on the stack. Also, if you *know* p will only be as an input and will not be changed, my syntax is OK, although a #define would be better. SteveT Steve Litt March 2016 featured book: Quit Joblessness: Start Your Own Business http://www.troubleshooters.com/startbiz ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Exactly, to modify a pointer you need a pointer to that pointer. Remember in C, function parameters are "read only" because they're always copies of the calling variable's values. This is wrong: function abcd(void *p) { p = malloc(sizeof(int)); // Memory leaking *p = 1; } main () { int *p = malloc(sizeof(int)); // [1] *p = 0; abcd(p); // Sends a copy of the value of p // p is still pointing to memory reserved by [1], so *p equals 0 } This is OK: function abcd(void **p) { *p = malloc(sizeof(int)); **p = 1; } main() { int i = 0; int *p = &i; // p has the address where i is located // Here *p is 0 efgh(&p); // Sends a copy of the address where p is stored // Now p is pointing to some address in the heap segment, and *p is 1 } IMHO you need to be careful when allocating memory inside functions. In some cases it would be a good practice checking the value of the pointer before allocating (!null) to avoid memory leaking. However, if you look at this last example, p is pointing to local memory, and you can overwrite it's value safely (so checking if p is not null before allocating wouldn't be any help). But, if you call this function twice, you will leak memory: efgh(&p); // [1] efgh(&p); // Now you can't free the memory reserved at [1] Cheers, Emiliano. On Mon, Mar 28, 2016 at 4:55 PM, Edward Bartolo wrote: > Hi, > > Thanks for dedicating some of your time to answer me. I used: > > void change_value(void** ptr) > > Because I wanted to enable myself to allocate memory for the pointer > inside the function, therefore I needed a pointer to a pointer of type > void. Void allows such a function to handle different data types in > which case an ordinal typed parameter may be used to allow a switch > statement within the function to handle the different data types. I > used such a construct in Delphi Pascal in the past, and consider it a > powerful feature that can have its uses. This is why I am anxious to > comprehend the why behind pointer to pointer use. > > This is a program employing the use of a pointer to change the value > of a parameter inside a function. > > #include > #include > > int afunc(double* dd) { > *dd *= 2; > } > > int main() { > double* mm; > mm = malloc(sizeof(double)); > printf("value of mm after creation, unassigned: %f\n", *mm); > *mm = 1.0; > > int j; > for (j = 1; j <= 20; j++) { > afunc(mm); > printf("value of mm after function call %d: %f\n", j, *mm); > } > > free(mm); > > return 0; > } > > I will post tomorrow a reply illustrating the allocation of memory to > a pointer within a function. This means the function must be able to > modify the pointer not only its data. For that I will probably need a > pointer to a pointer or use typecasting with a standard data type > having the same number of bytes as a pointer. The reason for this is > the fact that a pointer is a number. > > I found using the return value of a function makes code much more > readable and probably more reliable. Multiple return values can be > encapsulated inside a structure which would be returned by a function. > I used this construct in simple-netaid-lightweight which avoids the > use of GtkBuilder. > > Edward > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi, Thanks for dedicating some of your time to answer me. I used: void change_value(void** ptr) Because I wanted to enable myself to allocate memory for the pointer inside the function, therefore I needed a pointer to a pointer of type void. Void allows such a function to handle different data types in which case an ordinal typed parameter may be used to allow a switch statement within the function to handle the different data types. I used such a construct in Delphi Pascal in the past, and consider it a powerful feature that can have its uses. This is why I am anxious to comprehend the why behind pointer to pointer use. This is a program employing the use of a pointer to change the value of a parameter inside a function. #include #include int afunc(double* dd) { *dd *= 2; } int main() { double* mm; mm = malloc(sizeof(double)); printf("value of mm after creation, unassigned: %f\n", *mm); *mm = 1.0; int j; for (j = 1; j <= 20; j++) { afunc(mm); printf("value of mm after function call %d: %f\n", j, *mm); } free(mm); return 0; } I will post tomorrow a reply illustrating the allocation of memory to a pointer within a function. This means the function must be able to modify the pointer not only its data. For that I will probably need a pointer to a pointer or use typecasting with a standard data type having the same number of bytes as a pointer. The reason for this is the fact that a pointer is a number. I found using the return value of a function makes code much more readable and probably more reliable. Multiple return values can be encapsulated inside a structure which would be returned by a function. I used this construct in simple-netaid-lightweight which avoids the use of GtkBuilder. Edward ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Roger Leigh writes: > On 28/03/2016 15:35, Steve Litt wrote: >> On Mon, 28 Mar 2016 06:03:13 -0400 >> Boruch Baum wrote: >> >>> Why on this list, of all the possible places in Creation? It's a great >>> and important topic, but have you found no other, more appropriate >>> forum? > >> Because we're developing software. > > I'd have to say that while I'm mostly just an observer here, I do > consider this thread close to noise with precious little of value in > it. And complaints about the horror of having to ignore discussions about topics one isn't interested in have exactly no value. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On 28/03/2016 15:35, Steve Litt wrote: On Mon, 28 Mar 2016 06:03:13 -0400 Boruch Baum wrote: Why on this list, of all the possible places in Creation? It's a great and important topic, but have you found no other, more appropriate forum? > Because we're developing software. I'd have to say that while I'm mostly just an observer here, I do consider this thread close to noise with precious little of value in it. While it's certainly true that the list is related to software development (or would that be better stated as distribution development, which is somewhat higher-level?), it's also true that there are plenty of more appropriate forums for basic and intermediate C questions, and also a vast wealth of books and other materials which cover it in great detail. Kind regards, Roger ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
k...@aspodata.se writes: > Rainer Weikusat: > ... >> One thing to note here: Every C pointer is really a pointer to an array >> of values, although the size of the array may just be one. > ... > > I thought it was the other way around, a pointer is just an address to > some (a single) memory location which can be part of an array, I'd > not consider int ii to be an array even though int *pp = &ii, > -- but who cares. What I was trying to get at was that C doesn't differentiate between 'pointer to object' and 'pointer to array of objects': Assuming that p is a valid pointer, the object pointed to by p can always be accessed both via *p and via p[0] and p + 1 will always be a valid pointer, too, either one pointing to the next element of the array if there are at least two elements or the 'just beyond the end' pointer guaranteed to be usable for size calculations via pointer subtractions. This is also true if the pointer was implicitly created by using an expression of array type for something other than "[...] the operand of the sizeof operator or the unary & operator, or [...] a string literal used to initialize an array" Eg, after the following array definition int a[] = {0, 1, 2}; *a is a valid expression for accessing the first element. > But there is a real differnce between > int arr[10]; > and > int *pp = calloc(10, sizeof(int)); > as pp can be assigned to, but not arr, i.e. pp = malloc() works > but not arr = malloc(). The pointer arr is converted to is not an lvalue. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
I was wrong because in this examples p was a pointer to int. Sorry, I was thinking on something like this: int *p; *p = 0; Cheers, Emiliano. On Mon, Mar 28, 2016 at 2:16 PM, Emiliano Marini wrote: > You're right. > > On Mon, Mar 28, 2016 at 2:04 PM, Rainer Weikusat < > rainerweiku...@virginmedia.com> wrote: > >> Emiliano Marini writes: >> > char *p; >> > p="01234"; /* skeezy, but makes the point */ >> > >> > Warning! Here "p" is pointing to nowhere, you don't know which memory >> > locations are writing to. >> >> The 'memory location' (if any) reserved for the pointer p itself by the >> compiler, IOW, this is totally correct. >> >> > >> > char *p; >> > *p=malloc...* >> > p="01234"; /* skeezy, but makes the point */ >> >> And this is a memory leak as the pointer returned by malloc is >> overwritten. >> ___ >> Dng mailing list >> Dng@lists.dyne.org >> https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng >> > > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
You're right. On Mon, Mar 28, 2016 at 2:04 PM, Rainer Weikusat < rainerweiku...@virginmedia.com> wrote: > Emiliano Marini writes: > > char *p; > > p="01234"; /* skeezy, but makes the point */ > > > > Warning! Here "p" is pointing to nowhere, you don't know which memory > > locations are writing to. > > The 'memory location' (if any) reserved for the pointer p itself by the > compiler, IOW, this is totally correct. > > > > > char *p; > > *p=malloc...* > > p="01234"; /* skeezy, but makes the point */ > > And this is a memory leak as the pointer returned by malloc is > overwritten. > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
The main difference here is where you are storing the value "2000". In the first example, p is located in addresses belonging to "main" memory space (the stack presumably, beacuse "main" is the first function called upon start). You are passing the memory address of p (where p is located) to the function "change_value". The function assumes the memory address you are passing it's valid (meaning that it can be written safely). If you call "change_value" with null or with an invalid address (an address outside of all segments) you will cause a segfault. In the second example, "change_value" creates a new memory space (in the heap) to store "2000". This means you aren't "changing" anything. Every time you call "change_value" it creates a new """instance""" of "2000". Plus, if you don't free p before calling it again ("change_value(&p)"), you will be trashing memory (memory that cannot be released later, because you don't know their addresses). On Mon, Mar 28, 2016 at 3:50 AM, Edward Bartolo wrote: > Hi, > > As the title of the email indicates, I am doing some exercises to make > sense out of C pointer syntax. I have been using pointers for as long > as I have been programming without issues, apart from the usual > initial programmatic errors when new code is run for the first time. > However, C pointer syntax is proving to be as unintuitive as it can > be. For this reason, I am doing some exercises regarding C pointer > use. > > I am attaching two short C programs that I created and which I tested > to work although the mechanism by which they work is still somewhat > hazy to me. Both programs use a function to change the value of a > parameter. I want to understand, as opposed to knowing by rote, the > mechanism why they work. Please note that I didn't consult any books > to create the pointers. This is because I have already the concepts, > but I cannot make sense, as in deeply understanding the details, of > pointer syntax as used in C. > > Edward > > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Emiliano Marini writes: > char *p; > p="01234"; /* skeezy, but makes the point */ > > Warning! Here "p" is pointing to nowhere, you don't know which memory > locations are writing to. The 'memory location' (if any) reserved for the pointer p itself by the compiler, IOW, this is totally correct. > > char *p; > *p=malloc...* > p="01234"; /* skeezy, but makes the point */ And this is a memory leak as the pointer returned by malloc is overwritten. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
char *p; p="01234"; /* skeezy, but makes the point */ Warning! Here "p" is pointing to nowhere, you don't know which memory locations are writing to. char *p; *p=malloc...* p="01234"; /* skeezy, but makes the point */ On Mon, Mar 28, 2016 at 12:59 PM, Steve Litt wrote: > On Mon, 28 Mar 2016 14:51:19 +0200 (CEST) > k...@aspodata.se wrote: > > > Rainer Weikusat: > > ... > > > One thing to note here: Every C pointer is really a pointer to an > > > array of values, although the size of the array may just be one. > > ... > > > > I thought it was the other way around, a pointer is just an address to > > some (a single) memory location which can be part of an array > > You're both right. A pointer is definitely an address of a single > memory address of a single byte or char or int or whatever, but that > single memory address *could* be the first element of an array, thus > defining the beginning location of the whole array. And of course the > end of the array must be defined by a second pointer, an integer > length, or a sentinel value such as '\0' or NULL. > > char *p; > p="01234"; /* skeezy, but makes the point */ > printf("p points to char %c\n", *p); > printf("p indicates start of string %s\n", p); > > > SteveT > > Steve Litt > March 2016 featured book: Quit Joblessness: Start Your Own Business > http://www.troubleshooters.com/startbiz > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Steve Litt: ... > Years ago I gave up trying to logically explain the syntax of function > pointers, which are so essential for callbacks and pseudo-oop, and just > memorized the idiom. > > Edition 1 of K&R had an actual algorithm by which one could dissect any > lvalue (thing that can appear on the left of the equal sign), but it > was so complicated I couldn't understand it. So I memorized the idiom > for function pointers. > > I think C would have been much more successful (and it's already been > quite successful) if it could have had a better syntax for function > pointers. Too late to change that, but I think you are better off if you do a typedef first, as in: typedef int (*func_t)(int,int); int add(int a, int b) { return a + b; } int proc(func_t f, int a, int b) { return f(a,b); } int main(void) { int ix = 0; func_t func_arr[10]; func_arr[0] = add; return proc(func_arr[ix], 1, 2); } $ gcc -Wall a.c $ ./a.out $ echo $? 3 > I think the reason you see so few callback functions in > average C code is the syntax, Just because c gives you the possibility to make code that looks like tty noise, doesn't mean you have to... > as well as the unforgivingly strict typing > of the arguments. ... The strict typing comes with the language, but you can get around it with pointers (gives you 0 to x number of arguments, same type unless the type is void). You can use varargs, and a remote possibility is to pass down a string and parse it which is quite radable from the calling side :) Regards, /Karl Hammar --- Aspö Data Lilla Aspö 148 S-742 94 Östhammar Sweden +46 173 140 57 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Hi Boruch, On 03/28/2016 02:00 PM, Boruch Baum wrote: Why on this list, of all the possible places in Creation? It's a great and important topic, but have you found no other, more appropriate forum? This is an appropiate list to argue about pointers. Have a look at the code of some projects like vdev or the backend of simple-netaid. Cheers, Aitor. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Mon, 28 Mar 2016 12:28:03 +0200 (CEST) k...@aspodata.se wrote: > To exemplify the "as they are used" statement, take a function > pointer declaration: > > void (*log_func)(int priority, const char *format); > > here you cannot conveniently move the "*" to the "void" so it will > look like a "pointer" declaration; it declares log_func to be > something which if used as (*log_func)(a, b, d) will "give" you a > void value. Years ago I gave up trying to logically explain the syntax of function pointers, which are so essential for callbacks and pseudo-oop, and just memorized the idiom. Edition 1 of K&R had an actual algorithm by which one could dissect any lvalue (thing that can appear on the left of the equal sign), but it was so complicated I couldn't understand it. So I memorized the idiom for function pointers. I think C would have been much more successful (and it's already been quite successful) if it could have had a better syntax for function pointers. I think the reason you see so few callback functions in average C code is the syntax, as well as the unforgivingly strict typing of the arguments. Some time compare what it takes to do a callback in C compared to Python, or especially Lua. SteveT Steve Litt March 2016 featured book: Quit Joblessness: Start Your Own Business http://www.troubleshooters.com/startbiz ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
On Mon, 28 Mar 2016 14:51:19 +0200 (CEST) k...@aspodata.se wrote: > Rainer Weikusat: > ... > > One thing to note here: Every C pointer is really a pointer to an > > array of values, although the size of the array may just be one. > ... > > I thought it was the other way around, a pointer is just an address to > some (a single) memory location which can be part of an array You're both right. A pointer is definitely an address of a single memory address of a single byte or char or int or whatever, but that single memory address *could* be the first element of an array, thus defining the beginning location of the whole array. And of course the end of the array must be defined by a second pointer, an integer length, or a sentinel value such as '\0' or NULL. char *p; p="01234"; /* skeezy, but makes the point */ printf("p points to char %c\n", *p); printf("p indicates start of string %s\n", p); SteveT Steve Litt March 2016 featured book: Quit Joblessness: Start Your Own Business http://www.troubleshooters.com/startbiz ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Because we're developing software. On Mon, 28 Mar 2016 06:03:13 -0400 Boruch Baum wrote: > Why on this list, of all the possible places in Creation? It's a great > and important topic, but have you found no other, more appropriate > forum? > > On 03/28/2016 02:50 AM, Edward Bartolo wrote: > > Hi, > > > > As the title of the email indicates, I am doing some exercises to > > make sense out of C pointer syntax. I have been using pointers for > > as long as I have been programming without issues, apart from the > > usual initial programmatic errors when new code is run for the > > first time. However, C pointer syntax is proving to be as > > unintuitive as it can be. For this reason, I am doing some > > exercises regarding C pointer use. > > > > I am attaching two short C programs that I created and which I > > tested to work although the mechanism by which they work is still > > somewhat hazy to me. Both programs use a function to change the > > value of a parameter. I want to understand, as opposed to knowing > > by rote, the mechanism why they work. Please note that I didn't > > consult any books to create the pointers. This is because I have > > already the concepts, but I cannot make sense, as in deeply > > understanding the details, of pointer syntax as used in C. > > > > Edward ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Rainer Weikusat: > k...@aspodata.se writes: ... > > With pointers, you have to handle the special case of null pointers. > > I'm assuming you are omitting it here for brevity, but generally > > change_value() should be something like: > > > > void change_value(int* ptr) { > > if (!ptr) return; > > *ptr = 2000; > > } > > It absolutely shouldn't unless NULL is expected to be valid, used > argument value for some reason. If not, code passing NULL to such a > function is likely erroneous. Forcing the program to abort, preferably > with a core dump, via SIGSEGV will often enable fixing the error easily > and quick. Silently bouncing it out of the function again so that it > further propagates through the program is a terribly risky practice with > literally unpredictable consequences. Ok, I see your point (I'm used to functions that do error logging and error returns, maybe if(!ptr) abort() would suit you better, but that would incur non productive overhead, even though it better states what happens for this special case). But are you saying that the def. func(int * pp) says that null's are not allowed unless specifically allowed ? I somehow regards pp in func(int * pp) to be whatever you can put into an int*, no exceptions, and func() has to be able to handle the heat. For the actual function change_value(), what is the semantics to changing something that doesn't exist ? It could be abort() but it could just as well be just a no-op, choose your pick. You can compare it to the array case for (ix = 0; ix < arr_max; ix++) { change_value(arr + ix); } If the array is empty, that would be a big no-op. Or would you choose an abort() when arr_max == 0 ? /// But we can agree on that you have to be careful about null pointers. Regards, /Karl Hammar --- Aspö Data Lilla Aspö 148 S-742 94 Östhammar Sweden +46 173 140 57 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Rainer Weikusat: > k...@aspodata.se writes: ... > > To exemplify the "as they are used" statement, take a function pointer > > declaration: > > > > void (*log_func)(int priority, const char *format); > > > > here you cannot conveniently move the "*" to the "void" so it will look > > like a "pointer" declaration; it declares log_func to be something which > > if used as (*log_func)(a, b, d) will "give" you a void value. > > Unless something more interesting is being done, function pointers don't > need to be dereferenced, they can be used just like functions. ... You need it in the declaration, but not in the use, but I didn't want to confuse the matter. Regards, /Karl Hammar --- Aspö Data Lilla Aspö 148 S-742 94 Östhammar Sweden +46 173 140 57 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Rainer Weikusat: ... > One thing to note here: Every C pointer is really a pointer to an array > of values, although the size of the array may just be one. ... I thought it was the other way around, a pointer is just an address to some (a single) memory location which can be part of an array, I'd not consider int ii to be an array even though int *pp = &ii, -- but who cares. But there is a real differnce between int arr[10]; and int *pp = calloc(10, sizeof(int)); as pp can be assigned to, but not arr, i.e. pp = malloc() works but not arr = malloc(). Regards, /Karl Hammar --- Aspö Data Lilla Aspö 148 S-742 94 Östhammar Sweden +46 173 140 57 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
k...@aspodata.se writes: [...] > With pointers, you have to handle the special case of null pointers. > I'm assuming you are omitting it here for brevity, but generally > change_value() should be something like: > > void change_value(int* ptr) { > if (!ptr) return; > *ptr = 2000; > } It absolutely shouldn't unless NULL is expected to be valid, used argument value for some reason. If not, code passing NULL to such a function is likely erroneous. Forcing the program to abort, preferably with a core dump, via SIGSEGV will often enable fixing the error easily and quick. Silently bouncing it out of the function again so that it further propagates through the program is a terribly risky practice with literally unpredictable consequences. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Edward Bartolo: ... > I am attaching two short C programs that I created and which I tested > to work although the mechanism by which they work is still somewhat > hazy to me. ... Some comments on test101.c #include void change_value(void* ptr) { *((int*) ptr) = 2000; } int main() { int p = 8; printf("p = %d\n", p); change_value(&p); printf("p = %d\n", p); return 0; } The definition "void change_value(void* ptr);" doesn't preclude the use double dd; change_value(&dd); You don't handle things other than int's, so don't invite the user of change_value() to use anything else, why the "void *ptr" (it only gives you headaches with casts) ? You'd be better off writing it as: void change_value(int* ptr) { *ptr = 2000; } Don't use single letter variables unless you have a as short scope as you have in your main(). Using pp instead of p makes it much easier to find in a simple editor or with grep, or with your own eyes. With pointers, you have to handle the special case of null pointers. I'm assuming you are omitting it here for brevity, but generally change_value() should be something like: void change_value(int* ptr) { if (!ptr) return; *ptr = 2000; } since the func. is defined as "void change_value(int* ptr);", and generally, users shouldn't be required to read the function body to realize that the null pointer is forbidden. /// Some comments on test102.c === #include #include void change_value(void** ptr) { int* i = (int*) malloc(sizeof(int)); *i = 10001002; *ptr = i; } int main() { int* p; //printf("p = %d\n", p); change_value((void**) &p); printf("p = %d\n", *p); free(p); return 0; } === Same comments as for test101.c, plus: If you use void change_value(int ** ptr) {} instead, your call in main() will simplify to change_value(&p); /* instead of change_value((void**) &p); */ as you don't need the cast any longer (you didn't need it for the void case either, but your compiler might have complained). It will also simplify (ignoring null pointers for the moment) the body to void change_value(int ** ptr) { * ptr = (int *) malloc(sizeof(int)); ** ptr = 10001002; } malloc() inside a function and free() outside it invites to memory leaks, don't do that to yourself. Something like void *mem = malloc(...); func_call(...); free(mem); is way more easy to debug. Yes, that doesn't map wery good to your example, but you might benefit from rethinking how you use malloc/free. /// Regards, /Karl Hammar --- Aspö Data Lilla Aspö 148 S-742 94 Östhammar Sweden +46 173 140 57 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
k...@aspodata.se writes: [...] > To exemplify the "as they are used" statement, take a function pointer > declaration: > > void (*log_func)(int priority, const char *format); > > here you cannot conveniently move the "*" to the "void" so it will look > like a "pointer" declaration; it declares log_func to be something which > if used as (*log_func)(a, b, d) will "give" you a void value. Unless something more interesting is being done, function pointers don't need to be dereferenced, they can be used just like functions. And vice-versa. Eg, this useless little program converts all its arguments to ints and prints a message stating if they were odd or even twice: --- #include #include static void even(int d) { printf("%d is even\n", d); } static void odd(int d) { printf("%d is odd\n", d); } static void (*f[])(int) = { even, odd }; int main(int argc, char **argv) { int i; while (*++argv) { i = atoi(*argv); /* function name used as expression turns into function pointer */ (i & 1 ? odd : even)(i); /* function pointer can be used like function */ f[i & 1](i); } return 0; } -- ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Edward Bartolo writes: > As the title of the email indicates, I am doing some exercises to make > sense out of C pointer syntax. I have been using pointers for as long > as I have been programming without issues, apart from the usual > initial programmatic errors when new code is run for the first time. > However, C pointer syntax is proving to be as unintuitive as it can > be. For this reason, I am doing some exercises regarding C pointer > use. [...] > #include > > void change_value(void* ptr) { > *((int*) ptr) = 2000; > } You could have declared that as int *ptr in order to get rid of the cast. Also, the precedence is such that *(int *)p = 2000; would work. [...] > #include > #include > > void change_value(void** ptr) { This is a somewhat dubious construct as every pointer is required to be convertible from and to void * but not void **. > int* i = (int*) malloc(sizeof(int)); The cast is not necessary. And you don't really need the intermediate pointer. --- #include #include void change_value(int **ptr) { *ptr = malloc(sizeof(**ptr)); **ptr = 10001002; } int main() { int* p; change_value(&p); printf("p = %d\n", *p); free(p); return 0; } -- This becomes much less arcane-looking when letting go of the Pascal-y 'bad habit' of using pass-by-reference to create procedure returning values. -- #include #include int *array_1(void) { int *pi; pi = malloc(sizeof(*pi)); *pi = 10001002; return pi; } int main() { int* p; p = array_1(); printf("p = %d\n", *p); free(p); return 0; } -- One thing to note here: Every C pointer is really a pointer to an array of values, although the size of the array may just be one. Given the above, both *p and p[0] are equally legitimate ways to access the value. As per C definition, p[0] can also be written as 0[p] or *(p + 0) the same being true for any other valid (not out-of-bounds) index. ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Edward Bartolo: ... > However, C pointer syntax is proving to be as unintuitive as it can > be. ... > I want to understand, as opposed to knowing by rote, the > mechanism why they work. ... /// I think one source of confusion re. c-pointers is that they are declared "as they are used", but you migth not use them like that. If you take int *ix; then *ix will be an int, and you can _deduce_ that ix is a pointer to an int, but you don't say that directly. In your code you try to avoid the issue by writing "int* i;" and treating "int*" to be a "pointer" declaration. But "int * i ;" is four tokens regardless how you write it, you could just as well have written it as "int*i;" or "int *i;", same thing. To exemplify the "as they are used" statement, take a function pointer declaration: void (*log_func)(int priority, const char *format); here you cannot conveniently move the "*" to the "void" so it will look like a "pointer" declaration; it declares log_func to be something which if used as (*log_func)(a, b, d) will "give" you a void value. /// There is also a visual mismatch in c with a declaration of a pointer with an initializer. Example: int *ix = (int *) malloc(sizeof(int)); This line is the same thing as int *ix; /* i.e. *ix is an int */ ix = (int *) malloc(sizeof(int)); /* look no "*" */ So, int *ix = value; says two things; a: it declares an "ix" such as when ix is used as "*ix" it will be an int b: ix = value Another example is: #include #include void (*log_vfunc)(int priority, const char *format, va_list ap) = vsyslog; where the last line is the same thing as: void (*log_vfunc)(int priority, const char *format, va_list ap); log_vfunc = vsyslog; Regards, /Karl Hammar --- Aspö Data Lilla Aspö 148 S-742 94 Östhammar Sweden +46 173 140 57 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
Re: [DNG] Making sense of C pointer syntax.
Why on this list, of all the possible places in Creation? It's a great and important topic, but have you found no other, more appropriate forum? On 03/28/2016 02:50 AM, Edward Bartolo wrote: > Hi, > > As the title of the email indicates, I am doing some exercises to make > sense out of C pointer syntax. I have been using pointers for as long > as I have been programming without issues, apart from the usual > initial programmatic errors when new code is run for the first time. > However, C pointer syntax is proving to be as unintuitive as it can > be. For this reason, I am doing some exercises regarding C pointer > use. > > I am attaching two short C programs that I created and which I tested > to work although the mechanism by which they work is still somewhat > hazy to me. Both programs use a function to change the value of a > parameter. I want to understand, as opposed to knowing by rote, the > mechanism why they work. Please note that I didn't consult any books > to create the pointers. This is because I have already the concepts, > but I cannot make sense, as in deeply understanding the details, of > pointer syntax as used in C. > > Edward > > > > ___ > Dng mailing list > Dng@lists.dyne.org > https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng > -- hkp://keys.gnupg.net CA45 09B5 5351 7C11 A9D1 7286 0036 9E45 1595 8BC0 ___ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng