From chris_berry-list-oclug-devel at jm-associates.com Wed Jun 15 18:20:47 2005 From: chris_berry-list-oclug-devel at jm-associates.com (Chris Berry) Date: Wed, 15 Jun 2005 18:20:47 -0700 Subject: [OCLUG-devel] C Error Handling Message-ID: <42B0D3EF.7070304@jm-associates.com> Ok, I'm learning a little basic error handling with input strings. The object is to prompt the user for a positive integer, and make them do it over again if any other input is entered. Here is what I have right now: #include #define MAXLINE 100 int main (void) { char line[MAXLINE]; int error, n; do { printf ("Input a positive integer: "); fgets (line, MAXLINE, stdin); if (sscanf (line, "%[0-9]", &n) == 1) { error = 0; } else error = 1; if (error) printf ("\nERROR: Do it again.\n"); } while (error); return 0; } This works correctly for the following inputs: 3 -3 e e3 but not for: 3e Which it sees as valid input. I think the problem is that it quits as soon as it sees the invalid character, but I haven't quite been able to wrap my ahead around how to get it to keep looking without creating an infinite loop. Tried a few different things and looked on google but I think I'm not looking at it right yet. Can someone give me a hint? -- Chris Berry chris_berry at jm-associates.com Information Advisory Manager JM Associates "There is nothing so useless as doing efficiently that which should not be done at all." --Peter Drucker From x at xman.org Wed Jun 15 19:07:39 2005 From: x at xman.org (Christopher Smith) Date: Wed, 15 Jun 2005 19:07:39 -0700 Subject: [OCLUG-devel] C Error Handling In-Reply-To: <42B0D3EF.7070304@jm-associates.com> References: <42B0D3EF.7070304@jm-associates.com> Message-ID: <42B0DEEB.4050707@xman.org> Chris Berry wrote: > Which it sees as valid input. I think the problem is that it quits as > soon as it sees the invalid character, but I haven't quite been able > to wrap my ahead around how to get it to keep looking without creating > an infinite loop. Tried a few different things and looked on google > but I think I'm not looking at it right yet. Can someone give me a hint? Hmm.. some functional decomposition might help here. Make a function with this kind of a prototype: enum valid_response { invalid = 0, valid}; valid_response isValid(const char* aLine); Also a function for actually getting the line (this is just tidyness): void getInput(char* aLine) { printf("Input a positive integer: "); fgets(aLine, MAXLINE, stdin); } Then your loop is just: getInput(line); while (isValid(line) == invalid) { printf("\nError: Do it again.\n"); getInput(line); } The reason I suggest this functional decomposition is that it makes the program structure clearer, and it's easier to see where your problem is. Clearly, you aren't getting the response from isValid() that you want if aLine is "3e". So the question is, what is that criteria? Whatever it is should make 3e invalid, but you haven't defined it. I'm going to guess that the criteria is "all aLine's characters are numbers". So then you just need to do that. Something like: int isValid(const char* aLine) { const char* iter = aLine; while (*iter != '\0') { if (!isdigit(*iter)) { return invalid; } } return valid; } --Chris From chris_berry-list-oclug-devel at jm-associates.com Thu Jun 16 19:38:39 2005 From: chris_berry-list-oclug-devel at jm-associates.com (Chris Berry) Date: Thu, 16 Jun 2005 19:38:39 -0700 Subject: [OCLUG-devel] C Error Handling In-Reply-To: <42B0DEEB.4050707@xman.org> References: <42B0D3EF.7070304@jm-associates.com> <42B0DEEB.4050707@xman.org> Message-ID: <42B237AF.5020802@jm-associates.com> Well, that didn't quite work, and to top it off it threw in a nice infinite loop, but it did inspire me somewhat and here's the working code I came up with: #include #define MAXLINE 100 typedef enum valid_response { invalid = 0, valid } valid_response; valid_response is_valid (char *); void get_input (char *); int main (void) { char line[MAXLINE] = {}; get_input (line); while (is_valid(line) == invalid) { printf ("\nError: Do it again.\n"); get_input (line); } return 0; } void get_input (char * line) { printf("Input a positive integer: "); fgets (line, MAXLINE, stdin); } valid_response is_valid (char * line) { int i; for (i = 0; i < MAXLINE; i++) { if (isspace (line[i])) break; if (isdigit (line[i])) continue; if (!isdigit(line[i])) return invalid; } return valid; } Thanks for the help! Chris Berry chris_berry at jm-associates.com Information Advisory Manager JM Associates "There is nothing so useless as doing efficiently that which should not be done at all." --Peter Drucker Christopher Smith wrote: > Chris Berry wrote: > > >>Which it sees as valid input. I think the problem is that it quits as >>soon as it sees the invalid character, but I haven't quite been able >>to wrap my ahead around how to get it to keep looking without creating >>an infinite loop. Tried a few different things and looked on google >>but I think I'm not looking at it right yet. Can someone give me a hint? > > > Hmm.. some functional decomposition might help here. Make a function > with this kind of a prototype: > > enum valid_response { invalid = 0, valid}; > valid_response isValid(const char* aLine); > > Also a function for actually getting the line (this is just tidyness): > > void getInput(char* aLine) { > printf("Input a positive integer: "); > fgets(aLine, MAXLINE, stdin); > } > > Then your loop is just: > > getInput(line); > while (isValid(line) == invalid) { > printf("\nError: Do it again.\n"); > getInput(line); > } > > The reason I suggest this functional decomposition is that it makes the > program structure clearer, and it's easier to see where your problem is. > Clearly, you aren't getting the response from isValid() that you want if > aLine is "3e". So the question is, what is that criteria? Whatever it is > should make 3e invalid, but you haven't defined it. > > I'm going to guess that the criteria is "all aLine's characters are > numbers". So then you just need to do that. Something like: > > int isValid(const char* aLine) { > const char* iter = aLine; > while (*iter != '\0') { > if (!isdigit(*iter)) { > return invalid; > } > } > > return valid; > } > > --Chris From ddjolley at gmail.com Sun Jun 19 18:33:10 2005 From: ddjolley at gmail.com (Doug Jolley) Date: Sun, 19 Jun 2005 18:33:10 -0700 Subject: [OCLUG-devel] sizeof an array of pointers Message-ID: Hi, I'm using a library routine that defines array as 'char **array'. I thought I would be able to ascertain the size of the array (in bytes) by using 'sizeof(array)'. What I'm getting is '4' which is not the size of the array in bytes. It's not the number of elements in the array either. I think it MIGHT be the number of bytes in the pointer. So, my question is: What do I need to do to get the size of the array in bytes? My ultimate objective is to get the number of elements in the array; but, I think that should be fairly easy after I get the array size in bytes. Thanks for any input. ... doug -- (Not digitally signed.) From x at xman.org Sun Jun 19 19:27:53 2005 From: x at xman.org (Christopher Smith) Date: Sun, 19 Jun 2005 19:27:53 -0700 Subject: [OCLUG-devel] sizeof an array of pointers In-Reply-To: References: Message-ID: <42B629A9.6080302@xman.org> Doug Jolley wrote: >I'm using a library routine that defines array as 'char **array'. I >thought I would be able to ascertain the size of the array (in bytes) >by using 'sizeof(array)'. What I'm getting is '4' which is not the >size of the array in bytes. It's not the number of elements in the >array either. I think it MIGHT be the number of bytes in the pointer. > So, my question is: What do I need to do to get the size of the >array in bytes? My ultimate objective is to get the number of >elements in the array; but, I think that should be fairly easy after I >get the array size in bytes. > > You are right that it's returning the size of a pointer to char*. There is essentially no way to get the size of said array without some really hairy runtime specific hacking. The compiler can't possibly know the size at compile time, the runtime might know it depending on how memory allocation is done, but C doesn't provide a standard (or even semi-nonstandard) way to get at it. Normally libraries like this address the issue either by terminating the array with a null pointer or have a second argument somewhere that specifies the length of the array. I'd check the docs on the library. --Chris From ddjolley at gmail.com Sun Jun 19 20:20:11 2005 From: ddjolley at gmail.com (Doug Jolley) Date: Sun, 19 Jun 2005 20:20:11 -0700 Subject: [OCLUG-devel] sizeof an array of pointers In-Reply-To: <42B629A9.6080302@xman.org> References: <42B629A9.6080302@xman.org> Message-ID: > Normally libraries like this address > the issue either by terminating the array with a null pointer or have a > second argument somewhere that specifies the length of the array. I'd > check the docs on the library. The library does terminate the array with a null pointer. So, are you saying that the way to go is to just loop through the array and count the elements? I don't have any problem with that. I just thought that if there were a better way, I'd rather use it. Thanks, Chris, for the input. ... doug -- (Not digitally signed.) From x at xman.org Sun Jun 19 22:16:33 2005 From: x at xman.org (Christopher Smith) Date: Sun, 19 Jun 2005 22:16:33 -0700 Subject: [OCLUG-devel] sizeof an array of pointers In-Reply-To: References: <42B629A9.6080302@xman.org> Message-ID: <42B65131.1040405@xman.org> Doug Jolley wrote: >>Normally libraries like this address >>the issue either by terminating the array with a null pointer or have a >>second argument somewhere that specifies the length of the array. I'd >>check the docs on the library. >> >> > >The library does terminate the array with a null pointer. So, are you >saying that the way to go is to just loop through the array and count >the elements? I don't have any problem with that. I just thought >that if there were a better way, I'd rather use it. > >Thanks, Chris, for the input. > > Yeah, if you need to find out the size of the array, that'd be the way to do it. Normally you just want to perform some operations over the elements of the array so it's less of a hassle. You can save yourself a *tiny* bit of overhead for large arrays by using pointer arithmetic. Something like this: char** the_array = library_function(...); char** end_array = the_array; while (end_array != 0) { ++end_array; } /* now we know end_array is pointing just after the last element of the array */ size_t number_of_array_elements = (end_array - the_array) / sizeof(char*); So, that saves you one increment operation inside the loop. Depending on the speed of integer divide on your platform (these days it's effectively as fast as integer add), this becomes a net win as the array gets bigger. --Chris From x at xman.org Mon Jun 20 00:31:29 2005 From: x at xman.org (Christopher Smith) Date: Mon, 20 Jun 2005 00:31:29 -0700 Subject: [OCLUG-devel] sizeof an array of pointers In-Reply-To: <42B65131.1040405@xman.org> References: <42B629A9.6080302@xman.org> <42B65131.1040405@xman.org> Message-ID: <42B670D1.80609@xman.org> Christopher Smith wrote: > /* now we know end_array is pointing just after the last element of > the array */ > size_t number_of_array_elements = (end_array - the_array) / > sizeof(char*); > > So, that saves you one increment operation inside the loop. Depending > on the speed of integer divide on your platform (these days it's > effectively as fast as integer add), this becomes a net win as the > array gets bigger. Oh... how embarassing. I shouldn't write e-mails while trying to get a baby to go to sleep. :-( The divide is unecessary. Thanks to the wonder that is pointer arithmetic this is the correct way to do things: size_t number_of_array_elements = end_array - the_array; So, that should make this as efficient or more efficient than using a counter in almost all cases (zero-length arrays being the exception). --Chris From strombrg at dcs.nac.uci.edu Mon Jun 20 10:27:32 2005 From: strombrg at dcs.nac.uci.edu (Dan Stromberg) Date: Mon, 20 Jun 2005 10:27:32 -0700 Subject: [OCLUG-devel] sizeof an array of pointers In-Reply-To: <42B629A9.6080302@xman.org> References: <42B629A9.6080302@xman.org> Message-ID: <1119288452.22853.26.camel@seki.nac.uci.edu> On Sun, 2005-06-19 at 19:27 -0700, Christopher Smith wrote: > Doug Jolley wrote: > > >I'm using a library routine that defines array as 'char **array'. I > >thought I would be able to ascertain the size of the array (in bytes) > >by using 'sizeof(array)'. What I'm getting is '4' which is not the > >size of the array in bytes. It's not the number of elements in the > >array either. I think it MIGHT be the number of bytes in the pointer. > > So, my question is: What do I need to do to get the size of the > >array in bytes? My ultimate objective is to get the number of > >elements in the array; but, I think that should be fairly easy after I > >get the array size in bytes. > > > > > You are right that it's returning the size of a pointer to char*. There > is essentially no way to get the size of said array without some really > hairy runtime specific hacking. The compiler can't possibly know the > size at compile time, the runtime might know it depending on how memory > allocation is done, but C doesn't provide a standard (or even > semi-nonstandard) way to get at it. Normally libraries like this address > the issue either by terminating the array with a null pointer or have a > second argument somewhere that specifies the length of the array. I'd > check the docs on the library. Would it not be the size of a single pointer to char **? But anyway, that should be the same size as pointer to char * pretty much always - but I don't imagine it's guaranteed to be by the language. Anyway, if you can declare your array as: char array[10][20] ...then you'll likely find sizeof more helpful./ -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part Url : http://localhost.localdomain/pipermail/oclug-devel/attachments/20050620/46e3a9bc/attachment.bin From strombrg at dcs.nac.uci.edu Mon Jun 20 10:50:23 2005 From: strombrg at dcs.nac.uci.edu (Dan Stromberg) Date: Mon, 20 Jun 2005 10:50:23 -0700 Subject: [OCLUG-devel] sizeof an array of pointers In-Reply-To: <42B65131.1040405@xman.org> References: <42B65131.1040405@xman.org> Message-ID: <1119289823.22853.32.camel@seki.nac.uci.edu> On Sun, 2005-06-19 at 22:16 -0700, Christopher Smith wrote: > Doug Jolley wrote: > > >>Normally libraries like this address > >>the issue either by terminating the array with a null pointer or have a > >>second argument somewhere that specifies the length of the array. I'd > >>check the docs on the library. > >> > >> > > > >The library does terminate the array with a null pointer. So, are you > >saying that the way to go is to just loop through the array and count > >the elements? I don't have any problem with that. I just thought > >that if there were a better way, I'd rather use it. > > > >Thanks, Chris, for the input. > > > > > Yeah, if you need to find out the size of the array, that'd be the way > to do it. Normally you just want to perform some operations over the > elements of the array so it's less of a hassle. You can save yourself a > *tiny* bit of overhead for large arrays by using pointer arithmetic. > Something like this: > > char** the_array = library_function(...); > char** end_array = the_array; > while (end_array != 0) { > ++end_array; > } > /* now we know end_array is pointing just after the last element of the > array */ > size_t number_of_array_elements = (end_array - the_array) / sizeof(char*); > > So, that saves you one increment operation inside the loop. Depending on > the speed of integer divide on your platform (these days it's > effectively as fast as integer add), this becomes a net win as the array > gets bigger. Actually, even pretty primitive optimizers, by modern standards, should be able to rewrite array arithmetic to pointer arithmetic behind the scenes, which means you still get good code generated by the backend, without confusing the pascal programmers :) Also, ISTR that when you subtract a pointer from another pointer of the same type, the result is not the size of an element times the number of elements, but just the number of elements. For example: seki-strombrg> make clean; make rm -f *.o core array-arith gcc -g -ansi -Wall -pedantic array-arith.c -o array-arith ./array-arith size of entire array is 2000 Number of elements in the array is 201 Mon Jun 20 10:49:16 seki-strombrg> cat array-arith.c #include #define N 200 struct foo { char a[10]; } foo[N]; int main() { printf("size of entire array is %d\n",sizeof(foo)); printf("Number of elements in the array is %d\n", (&foo[N] - &foo[0])+1); return 0; } Mon Jun 20 10:49:20 ...which I guess just backs up the idea that pointer arithmetic is overcomplicated. :) -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part Url : http://localhost.localdomain/pipermail/oclug-devel/attachments/20050620/44a86653/attachment.bin From strombrg at dcs.nac.uci.edu Mon Jun 20 11:26:43 2005 From: strombrg at dcs.nac.uci.edu (Dan Stromberg) Date: Mon, 20 Jun 2005 11:26:43 -0700 Subject: [OCLUG-devel] sizeof an array of pointers In-Reply-To: <1119289823.22853.32.camel@seki.nac.uci.edu> References: <1119289823.22853.32.camel@seki.nac.uci.edu> Message-ID: <1119292003.22853.41.camel@seki.nac.uci.edu> On Mon, 2005-06-20 at 10:50 -0700, Dan Stromberg wrote: > printf("Number of elements in the array is %d\n", (&foo[N] - &foo[0])+1); Doh! Should be N-1, not N - I don't want to think about what a particularly fussy compiler+runtime would do with a reference to the N +1th element of an N element array. :) Probably fine most of the time, but likely not guaranteed. -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part Url : http://localhost.localdomain/pipermail/oclug-devel/attachments/20050620/4d2356de/attachment.bin From x at xman.org Mon Jun 20 12:08:02 2005 From: x at xman.org (Christopher Smith) Date: Mon, 20 Jun 2005 12:08:02 -0700 Subject: [OCLUG-devel] sizeof an array of pointers In-Reply-To: <1119288452.22853.26.camel@seki.nac.uci.edu> References: <42B629A9.6080302@xman.org> <1119288452.22853.26.camel@seki.nac.uci.edu> Message-ID: <42B71412.3030609@xman.org> Dan Stromberg wrote: > On Sun, 2005-06-19 at 19:27 -0700, Christopher Smith wrote: >>You are right that it's returning the size of a pointer to char*. > > Would it not be the size of a single pointer to char **? Nah. It's effectively doing sizeof(char**), which gives you "the size of a pointer to char*". The size of a pointer to char** would be doing sizeof(char***). As you noted, on nearly any system these will be the same size, but there is a semantic difference. --Chris From strombrg at dcs.nac.uci.edu Mon Jun 20 12:13:48 2005 From: strombrg at dcs.nac.uci.edu (Dan Stromberg) Date: Mon, 20 Jun 2005 12:13:48 -0700 Subject: [OCLUG-devel] sizeof an array of pointers In-Reply-To: <42B71412.3030609@xman.org> References: <1119288452.22853.26.camel@seki.nac.uci.edu> <42B71412.3030609@xman.org> Message-ID: <1119294828.22853.48.camel@seki.nac.uci.edu> On Mon, 2005-06-20 at 12:08 -0700, Christopher Smith wrote: > Dan Stromberg wrote: > > On Sun, 2005-06-19 at 19:27 -0700, Christopher Smith wrote: > >>You are right that it's returning the size of a pointer to char*. > > > > Would it not be the size of a single pointer to char **? > > Nah. It's effectively doing sizeof(char**), which gives you "the size of > a pointer to char*". The size of a pointer to char** would be doing > sizeof(char***). As you noted, on nearly any system these will be the > same size, but there is a semantic difference. > > --Chris Ah, I now agree. Thanks! -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part Url : http://localhost.localdomain/pipermail/oclug-devel/attachments/20050620/5041db2a/attachment.bin From x at xman.org Mon Jun 20 13:29:31 2005 From: x at xman.org (Christopher Smith) Date: Mon, 20 Jun 2005 13:29:31 -0700 Subject: [OCLUG-devel] sizeof an array of pointers In-Reply-To: <1119294828.22853.48.camel@seki.nac.uci.edu> References: <42B629A9.6080302@xman.org> <1119288452.22853.26.camel@seki.nac.uci.edu> <42B71412.3030609@xman.org> <1119294828.22853.48.camel@seki.nac.uci.edu> Message-ID: <42B7272B.3000308@xman.org> Dan Stromberg wrote: > On Mon, 2005-06-20 at 12:08 -0700, Christopher Smith wrote: >>Nah. It's effectively doing sizeof(char**), which gives you "the size of >>a pointer to char*". The size of a pointer to char** would be doing >>sizeof(char***). As you noted, on nearly any system these will be the >>same size, but there is a semantic difference. > Ah, I now agree. Thanks! Sometimes it's easier to parse C than English. ;-) --Chris From ddjolley at gmail.com Tue Jun 21 10:14:55 2005 From: ddjolley at gmail.com (Doug Jolley) Date: Tue, 21 Jun 2005 10:14:55 -0700 Subject: [OCLUG-devel] strcpy segmentation faults Message-ID: Hi. I'm very green but I'm really trying to learn C. I seem to keep coming up with segmentation fault errors and they always seem to occur within the context of a strcpy. I am appending an example function I wrote that is intended to remove the beginning part of a string up to the first occurrence of an underscore (_). I'm getting a segmentation fault and the strcpy seems to be the culprit. I am having similar problems elsewhere. Aside from wanting to know what my specific problem is in this case, I'm wondering what is the best procedure for trouble shooting segmentation faults. Thanks for any input. Here is the example: char *trim(char *p2c) { char *ptr1; /* If p2c contains an '_', trash it and any characters that prceed it. */ ptr1=strstr(p2c,"_"); if (ptr1!=NULL) strcpy(p2c,ptr1+1); return p2c; } ... doug -- (Not digitally signed.) From x at xman.org Tue Jun 21 13:36:24 2005 From: x at xman.org (Christopher Smith) Date: Tue, 21 Jun 2005 13:36:24 -0700 Subject: [OCLUG-devel] strcpy segmentation faults In-Reply-To: References: Message-ID: <42B87A48.7050605@xman.org> Doug Jolley wrote: > Hi. I'm very green but I'm really trying to learn C. I seem to keep > coming up with segmentation fault errors and they always seem to occur > within the context of a strcpy. Keep in mind that strcpy is a fairly dangerous function, as it will just keep going if it doesn't find a null byte. It's safer to use strncpy(). In this case it's pretty much a non-issue as you're already using strstr() which relies on the null byte being there as well. > I am appending an example function I > wrote that is intended to remove the beginning part of a string up to > the first occurrence of an underscore (_). I'm getting a segmentation > fault and the strcpy seems to be the culprit. I am having similar > problems elsewhere. Aside from wanting to know what my specific > problem is in this case, I'm wondering what is the best procedure for > trouble shooting segmentation faults. Generally, the best procedure is to load up the core file in gdb. That'll show you what specifically caused the fault, and then look at what it was accessing that was of memory. Then back trace through the stack to figure out how that happened. Alternatively, just run the thing in gdb from the get go. That tends to produce the best results, but everything runs more slowly. > Thanks for any input. Here is > the example: > > char *trim(char *p2c) > { > char *ptr1; > /* If p2c contains an '_', trash it and any characters that prceed it. */ > ptr1=strstr(p2c,"_"); > if (ptr1!=NULL) > strcpy(p2c,ptr1+1); > return p2c; > } Hmm... maybe your is different, but my man page for strcpy specifically says "The strings may not overlap" in the second sentence. ;-) That is what's causing your core dump. Note also that you are finding the first "_" and not the last. To find the last "_" use strrchr() instead of strstr. Even if you want the first, since the pattern you're matching against is a single character, I'd recommend using strchr(). --Chris From x at xman.org Tue Jun 21 17:23:01 2005 From: x at xman.org (Christopher Smith) Date: Tue, 21 Jun 2005 17:23:01 -0700 Subject: [OCLUG-devel] strcpy segmentation faults In-Reply-To: References: Message-ID: <42B8AF65.9050102@xman.org> I thought of another reason you might be having troubles with your code. Modern versions of gcc make all string constants actually constant, and if you modify them in any way, you get a segfault. So for example you'll get a segfault if you do trim("hello_world") as soon as you try to overwrite that 'h' with a 'w'. So, you need to make a copy of the string first. In general, since you are trying to do an in place modification of the string (not sure how good an idea that is, but there is merit to it depending on the situation), I'd not use strcpy, strncpy, or memcpy at all. Instead I'd just do it manually: char* trim(char* p2c) { /* copy the pointer so that we still have something to return to */ char* target_iter = p2c; char* source_iter; /* If p2c contains an '_', trash it and any character that proceed it. */ source_iter = strrchr(p2c, '_'); if (source_iter != NULL) { do { *target_iter++ = *++source_iter; } while (*source_iter != '\0'); } return p2c; } From ddjolley at gmail.com Thu Jun 23 20:54:52 2005 From: ddjolley at gmail.com (Doug Jolley) Date: Thu, 23 Jun 2005 20:54:52 -0700 Subject: [OCLUG-devel] Initializing an array of pointers Message-ID: I'm always amazed by how text book authors can bridge huge gaps with just a few words. I'm studying C from a text book and the author gives the following example: char *pS[3] = { NULL }; Then boldly says, "The difference, here, is that we now have an array of three pointers to char, called pS, each of which is initialized to NULL." I would certainl agree if he had said: char *pS[3] = { NULL, NULL, NULL }; In an earlier chapter he had said that in initializing arrays of pointers if there are fewer elements on the right than there are in the array, the remainder initialize to 0. Although he didn't say so, I suspect that he was talking about arrays of numeric elements. It would seem logical that if when initializing an array of pointers there are fewer elements on the right than there are in the array, the remainder would initialize to NULL. Assuming that's the case (and I'm not sure that it is), then why couldn't the array have been initialized like this: char *pS[3] = { }; IOW, if the default is NULL; then, why specify even one element. Anyway, I thought I would toss this out here. Thanks for any input. ... doug (Not digitally signed.) -- (Not digitally signed.) From ddjolley at gmail.com Thu Jun 23 23:01:12 2005 From: ddjolley at gmail.com (Doug Jolley) Date: Thu, 23 Jun 2005 23:01:12 -0700 Subject: [OCLUG-devel] strcpy segmentation faults In-Reply-To: <42BB0941.4060602@xman.org> References: <42B8AF65.9050102@xman.org> <42B8FC07.3050401@xman.org> <42BB0941.4060602@xman.org> Message-ID: > 5) Because it's declared "char*" (as opposed to const char*), > REALLY_CONSTANT itself is not constant, nor is it necessarily pointing > to a constant. It's just the stuff it's pointing to initially is > (because it's a literal string). Well, if you would have left out the phrase beginning with 'nor', I would have said that I get it. The difference between 'char*' and 'const char*' is that 'char*' is a pointer variable (that may be changed) and is pointing to a literal/constant string while 'const char*' is a pointer constant pointing to the same thing. So, in the first case we have a pointer variable that can be changed pointing to a literal/constant string and in the second case we have a constant pointer pointing to the same thing. That's what I would have said if you had omitted the phrase beginning with 'nor'. With that phrase I'm not sure what to think. It sounds like you see a distinction between a string constant and a string literal. I'm not sure I understand that distinction. In order to avoid obscuring the issue, let's take the pointers out of it for a minute. Do you see a difference between: char myVar[] = "My dog has fleas."; and const myVar char[] = "My dog has fleas."; Before we began this discussion I would have said that the difference is that the first is a variable that can be changed and the second is a constant that can't be changed. I thought what you were telling me is that there is now no difference. Have I missed the point here? It doesn't seem like loosing the flexibility to go either way would be an advantage. Am I confused? Thanks. ... doug (Not digitally signed.) From msimpson at braysimpson.com Fri Jun 24 12:02:42 2005 From: msimpson at braysimpson.com (Morgan Simpson) Date: Fri, 24 Jun 2005 12:02:42 -0700 Subject: [OCLUG-devel] strcpy segmentation faults In-Reply-To: References: <42B8AF65.9050102@xman.org> <42B8FC07.3050401@xman.org> <42BB0941.4060602@xman.org> Message-ID: On Jun 23, 2005, at 11:01 PM, Doug Jolley wrote: > Do you see a difference between: > char myVar[] = "My dog has fleas."; > and > const myVar char[] = "My dog has fleas."; In the second case, the compiler will (should) issue an error if you use "myVar" as an lvalue in an expression. A bigger issue arises with: char *myVar = "My dog has fleas."; // example 1 char myVar[] = "My dog has fleas."; // example 2 If you attempt to modify the string in example 1, you should get a segmentation fault because the GCC compiler stored the string in a read-only segment of memory. This problem does not occur with example 2 as the string resides in a writable segment of memory. If you want to safely modify the string in example 1, you need to use the GCC flag -fwritable-strings. Hope this helps. Regards, Morgan Simpson Bray, Simpson and Associates, Inc. From strombrg at dcs.nac.uci.edu Fri Jun 24 12:17:25 2005 From: strombrg at dcs.nac.uci.edu (Dan Stromberg) Date: Fri, 24 Jun 2005 12:17:25 -0700 Subject: [OCLUG-devel] strcpy segmentation faults In-Reply-To: References: Message-ID: <1119640645.22853.412.camel@seki.nac.uci.edu> On Fri, 2005-06-24 at 12:02 -0700, Morgan Simpson wrote: > On Jun 23, 2005, at 11:01 PM, Doug Jolley wrote: > > > Do you see a difference between: > > char myVar[] = "My dog has fleas."; > > and > > const myVar char[] = "My dog has fleas."; > > In the second case, the compiler will (should) issue an error if you > use "myVar" as an lvalue in an expression. A bigger issue arises with: > > char *myVar = "My dog has fleas."; // example 1 > char myVar[] = "My dog has fleas."; // example 2 > > If you attempt to modify the string in example 1, you should get a > segmentation fault because the GCC compiler stored the string in a > read-only segment of memory. This problem does not occur with example 2 > as the string resides in a writable segment of memory. If you want to > safely modify the string in example 1, you need to use the GCC flag > -fwritable-strings. I gather that gcc 4.0.0 drops support of the -fwritable-strings flag, but prior versions of gcc should have it - though I'm not 100% sure that it will work on all platforms that gcc supports. From x at xman.org Fri Jun 24 12:52:56 2005 From: x at xman.org (Christopher Smith) Date: Fri, 24 Jun 2005 12:52:56 -0700 Subject: [OCLUG-devel] strcpy segmentation faults In-Reply-To: References: <42B8AF65.9050102@xman.org> <42B8FC07.3050401@xman.org> <42BB0941.4060602@xman.org> Message-ID: <42BC6498.7030805@xman.org> Doug Jolley wrote: >>5) Because it's declared "char*" (as opposed to const char*), >>REALLY_CONSTANT itself is not constant, nor is it necessarily pointing >>to a constant. It's just the stuff it's pointing to initially is >>(because it's a literal string). > > > Well, if you would have left out the phrase beginning with 'nor', I > would have said that I get it. The difference between 'char*' and > 'const char*' is that 'char*' is a pointer variable (that may be > changed) and is pointing to a literal/constant string while 'const > char*' is a pointer constant pointing to the same thing. No. a 'char*' is a pointer variable pointing to a string. In this case it starts out pointing to a string literal, but it need not be that way. Similarly, "const char*" is not a pointer constant. That'd be 'char* const' (and yes, that is a touch confusing). "const char*" means you have a non-constant pointer pointing to a constant string, or more accurately, a string that cannot be modified from said pointer (in practice the string need not be constant, so long as it's modified by accessing it from a different pointer). Perhaps the bigger point that is not being expressed well here is that typing information is *about the variable*, not about the value. So, you can have a "char*" and a "const char*" pointing to the same address. Different rules will apply to what you can do with data at that address depending on which variable you use to access it. Seperately, you can have restrictions on the memory at that address (i.e. it might be a literal, it might already be free()'d, etc.) > It sounds like you see a distinction between a string constant and > a string literal. I'm not sure I understand that distinction. There is a small and subtle difference. A string literal is a literal embedded in the code. It's value is embedded inside the program code. Based on recent revs of gcc and C99, it is required to be constant. However, you can also have a string constant that who's value is not embedded in the code. For example I might get the value from a database or a configuration file. To illustrate the point, here's some pseudo code: void illegal_foo(const char* bar) { bar[1] = 'c'; /* illegal, shouldn't compile */ } void foo(char* bar) { bar[1] = 'c'; } char* var1 = "can't change me"; const char* var2 = "safer way to define it"; char* var3 = (char*) alloca(strlen(var1)+1); const char* var4 = var3; strcpy(var3, var1); foo(var1); /* segfault */ foo(var2); /* illegal type for parameter "bar", shouldn't compile */ illegal_foo(var2); /* this is valid, but of course the definition of illegal_foo isn't so it's hardly of much value */ foo(var3); /* legal, and it won't segfault */ foo(var4); /* illegal, but if the compiler ignores const anyway, no segfault */ --Chris