Thread: char array pointers problem

  1. #1
    Registered User
    Join Date
    Jul 2004
    Posts
    68

    char array pointers problem

    Below is a small demonstration on an issue I am having in a much larger program. The error I am getting from gcc is

    test.c: In function `main':
    test.c:11: warning: passing arg 1 of `test_func' from incompatible pointer type
    I have marked line 11 with /* error */

    It has been quite a while since I last played around in C and for the life of me an after much searching cannot find what I am doing wrong.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    void test_func( char **t[5] );
    
    int main(void)
    {
    	char *messages[5];
    	int i;
    	
    	test_func( &messages ); /* error */
    
    	for ( i = 0; i < 5; i++ )
     		printf( "%s\n", messages[i] );
    	
    	return 0;
    }
    
    void test_func( char **t[5] )
    {
    	int i;
    	char *m[5] = {
    		"Testing 1 2 3",
    		"Another",
    		"And Again",
    		"Dont worry almost there",
    		"Ok done"
    		};
    
    	for ( i = 0; i < 5; i++ )
    	{
    		strcpy( *t[i], m[i] );
    	}
    
    	return ;
    }

  2. #2
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void test_func( char *t[]);
    
    int main(void)
    {
    	char *messages[5];
    	int i;
    	
    	test_func(messages);
    	
    	for ( i = 0; i < 5; i++ )
    		printf("&#37;s\n",messages[i]);
    	
    	return 0;
    }
    
    void test_func( char *t[])
    {
    	int i;
    	char *m[5] = {
    	"Testing 1 2 3",
    	"Another",
    	"And Again",
    	"Dont worry almost there",
    	"Ok done"
    	};
    
    	for ( i = 0; i < 5; i++ )
    	{
    		t[i] = (char *)malloc(strlen(m[i]) + 1);
    		strcpy(t[i], m[i]);
    	}
    	
    	return ;
    }
    Most significant changes in bold.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Nooo - not the casting malloc - see the FAQ
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Quote Originally Posted by Salem View Post
    Nooo - not the casting malloc - see the FAQ
    http://faq.cprogramming.com/cgi-bin/...&id=1043284351

    [Y]ou should use whichever you like provided you are aware of the issues.
    My own personal reasons for preferring the cast:

    1) I like to know the type of data when a malloc() is occurring, especially when reading through other people's code and the variable is named something obscure or just one letter and is a pointer to a pointer to a.... and they don't even know what data type they are allocating for (ie. char *, char **, or char ***).
    2) Compatability with C++.
    3) Intentions of the code are clearer imo. Sort of a restatement of reason 1.

    Reasons for not casting:

    1) Extra typing.
    2) It hides the fact you may have not included <stdlib.h>

    Do it, and you may cause problems. Don't do it, and you may cause problems. A C programmer has such a hard life.
    Last edited by MacGyver; 03-30-2007 at 10:45 AM.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > they are allocating for (ie. char *, char **, or char ***).
    But the size being passed to malloc is far more important to get right in that case.

    p = malloc ( n * sizeof *p );
    ALWAYS works - no exceptions.
    No need to work out whether it's a char* or a double *, the compiler can figure it out for itself.
    There is no need to care about what type p is pointing to at the time malloc is called. How p gets used later on will tell you a hell of a lot more about the type than the malloc will. So long as you manage to get the 'n' right, it's all goodness throughout.

    Compare with
    int *p;
    p = (int*)malloc( n * sizeof(int) );

    Say Mr maintenance guy comes along and decides that int is no longer good enough and it needs to be double.
    Now you have 3 points of failure instead of one.

    What if for some reason the programmer gets distracted, and the code winds up looking like this sorry example.
    double *p;
    p = (double*)malloc( n * sizeof(int) );
    He changed the line, so it must be right - right?
    The more you stare at something you've convinced yourself is right, the harder it becomes to realise there is actually something wrong with it.

    Likewise, if Mr maintenance comes across this line of code in something which has been working for a long time
    p = (double*)malloc( n * sizeof(int) );
    He's left wondering whether something really clever is going on, or something really dumb is going on. Either way, it's a lot of hard work for the poor chap to get to the bottom of it.

    Written the way I suggest you write it, all you need do is change
    int *p into double *p and the malloc AUTOMATICALLY does the right thing, no editing required.


    > 2) Compatability with C++.
    I had exactly the same argument with someone else on another board.
    If that were the ONLY difference between C and C++, then it might be OK.
    But it isn't, not by a long way - http://david.tribble.com/text/cdiffs.htm
    Polyglot programs essentially degenerate into the worse cases of all the languages involved. Trying to mix C and C++ is no exception.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    A combination of some of the forms you posted:

    Code:
    p = (int *)malloc(n * sizeof(*p));
    That way, if you do change p to a double, then all you need to change is the cast for every malloc(). You don't have to worry about anything else, and it's C++ compliant.

    If Mr. Maintenance has to move the code over to C++, he might have a lot of headaches, but at least the memory allocation should be fine if he needs to leave it the way it is.

    If there's no chance your code will ever be ported to C++, then the cast is not needed for this purpose, but I still believe the memory allocation is clearer this way as to what the programmer is intending to do. In C++, the memory allocation is clearer using new as opposed to malloc(), but we don't always get the choice to start the giant project in C++ originally.

    Either way, I just don't understand why people are beaten over the head for casting when the FAQ concludes that either style (to cast or not to cast) is valid, provided one knows what they are doing. If this site stands behind never casting, then I am somewhat confused as to why the FAQ has not be altered to reflect this.

    I don't feel like drawing this out to a long discussion, and I know there are many programmers that have been programming for years that do not like the cast, but I don't see how it will hurt them if I am more explicit with my memory allocation requests, especially when this is not against any of the C standards to my knowledge.

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Either way, I just don't understand why people are beaten over the head for casting when the FAQ concludes that either style (to cast or not to cast) is valid, provided one knows what they are doing. If this site stands behind never casting, then I am somewhat confused as to why the FAQ has not be altered to reflect this.
    I usually say "you shouldn't cast malloc", but you're right, many people say "don't cast malloc [it's evil]". I think one should not cast because that's why void pointers were invented. They were invented (well, in part) so that programmers wouldn't have to cast things.

    I don't feel like drawing this out to a long discussion
    It's certainly been done before. http://www.google.ca/search?q=cast+malloc
    http://cboard.cprogramming.com/archi...p/t-25799.html
    http://coding.derkeiler.com/Archive/...3-10/3601.html
    http://www.thescripts.com/forum/thread216060.html
    http://www.cpax.org.uk/prg/writings/casting.php
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  8. #8
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Piling on, somewhat, but...
    Quote Originally Posted by MacGyver View Post
    then all you need to change is the cast for every malloc()
    Don't we call that a maintenance nightmare when compared to not having to change unnecessary casts?


    If you were exclusively using C++, wouldn't you use (1) a vector, (2) new, (3) malloc with a C++-style cast, (4) malloc with a C-style cast?

    If you were exclusively using C, wouldn't you use just as the FAQ says?

    If you were coding some mixture of C and C++, why not isolate the C code in a separate module and make it C?

    If you really needed some C code intermixed within some C++ code in this fashion, I would say that it should be commented heavily as to the need. Otherwise if doing such is really a 3rd, 4th, or worse choice, why bother?

    And from this viewpoint of it being among the least desirable choices -- in beginner code, certainly, or many other cases -- given the alternatives, I think the "it's evil" is merely a quick way of saying all of that that more succinctly.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  9. #9
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    As I already said, that would be great if you know your C code will never need to become C++ code overnight. Sometimes -- or perhaps more properly usually -- the luxury of writing software that doesn't need to be changed is never realized.

    Everybody has beat this topic into the ground, except I think the admins/mods are missing the most important point. I already brought it up, but I suppose I should go into it in greater depth. Why doesn't the FAQ tell people that casting malloc() is wrong? The FAQ acknowledges that there are programmers that believe it is appropriate. To top it off, the FAQ concludes with saying that programmers should choose to cast or not based upon their own reasoning, as long as they recognize the issues surrounding it. Due to this, I find it ridiculous to tell people to read the FAQ as evidence that says that they should not cast, when the FAQ does not even reach that conclusion.

  10. #10
    Captain - Lover of the C
    Join Date
    May 2005
    Posts
    341
    Did you actually read the FAQ page:
    So should you cast malloc? No
    Seems pretty clear to me. What follows that statement is only there because there are a small number of cases when you would prefer to cast malloc.
    Don't quote me on that... ...seriously

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by MacGyver View Post
    As I already said, that would be great if you know your C code will never need to become C++ code overnight. Sometimes -- or perhaps more properly usually -- the luxury of writing software that doesn't need to be changed is never realized.
    Who the hell cares about people who may or may not decide to port your code to a different language in the future? If they want to convert it, let'm. It's not my job to see that they have an easy time of it by doing stupid stuff that serves no purpose.

    Casting *alloc never has a purpose in C. Ever. There is not one case where you gain anything by casting any of the allocation functions. Ever! That's why it returns a void *. You never have to typecast void * assignments in C. Ever. It's completely pointless to do so.

    They beat it into the ground, because it's completely pointless to ever cast it. It's a waste of keystrokes that serves no benefit other than to hide errors. There is no advantage in C to you taking the time to add the cast. Furthermore, as described in your feeble attempt to make it "easier" for people to convert it to C++, you're doing yourself a disservice to people who aren't trying to convert it to a different language, but are trying to switch data types.

    Say I add casts to help some future moron convert it to C++. It's now a harder task for someone to make my code allocate float instead of int now because of adding casts.

    So by your logic, you're damned if you do, and you're damned if you don't. Who do I help? Myself. That's who. Typecasting allocation functions is pointless and extra keystrokes which do absolutely nothing for my code. Everyone who knows anything about C knows that malloc allocates memory. All I have to know is that the item on the left, whatever it's type, is being allocated some blocks of memory. That's all. Why in the hell do I care to see a cast of what is being returned? Am I too stupid to look up a variable type if I need it all of this sudden?

    You know why it's been beaten into the ground so much? Because no matter how many times it's repeated, someone who can't admit it's pointless to do so comes along goes on and on about how they like to do it and boo hoo, don't tell them otherwise! Maybe if I add a few more lines about how pointless it is ... I'll still end up having to type it all over to the next moron that shows up.


    Quzah.
    Last edited by quzah; 03-30-2007 at 09:58 PM.
    Hope is the first step on the road to disappointment.

  12. #12
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Quote Originally Posted by Brad0407 View Post
    Did you actually read the FAQ page:
    Yes, I've read the FAQ multiple times. I've quoted from it. I've discussed it. I've stated my reasons for why I think casting is not "evil".

    I am amazed at the selective twist of the quote in your post, and to be completely honest, I am wondering if you even read my posts and the FAQ in their correct respective context.

    So should you cast malloc? No, that is the preferred method. However, you should use whichever you like provided you are aware of the issues.
    The FAQ is putting forth a good argument that says that casting is recommended against, but acknowledges that there is another valid school of thought on the subject. That should end the discussion with both sides of the fences recognizing the other, but for whatever reason that's not how it works. I have no idea why people get so serious over this.

    Seems pretty clear to me. What follows that statement is only there because there are a small number of cases when you would prefer to cast malloc.
    This makes no sense.

    Quote Originally Posted by quzah
    You know why it's been beaten into the ground so much? Because no matter how many times it's repeated, someone who can't admit it's pointless to do so comes along goes on and on about how they like to do it and boo hoo, don't tell them otherwise! Maybe if I add a few more lines about how pointless it is ... I'll still end up having to type it all over to the next moron that shows up.
    From my short experience here on these forums, it's beaten into the ground so much because the anti-cast crowd is obsessed that their way is the only way. Everytime they see someone cast, they waste more keystrokes talking about how evil it is then the person who is doing the casting.

    So who's the person really wasting time, when the FAQ concludes that one way is recommended, but both are acceptable? And incidentally, I don't believe I've ever said anything offensive to you, but if you prefer to think of me as a moron if I prefer to cast, then I see we'll get along just fine together.

  13. #13
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I never said they were evil. Just that they were wasting keystrokes, and lacking gray-matter.


    Quzah.
    Hope is the first step on the road to disappointment.

  14. #14
    Captain - Lover of the C
    Join Date
    May 2005
    Posts
    341
    >> This makes no sense.
    Read it again. It's english with an average word length of 4.5 letters. I think my little brother could handle it.

    >> I am amazed at the selective twist of the quote in your post
    I acknowledged the rest of the text. I said "What follows that statement is only there because there are a small number of cases when you would prefer to cast malloc."

    >> So who's the person really wasting time, when the FAQ concludes that one way is recommended, but both are acceptable?
    Yeah. They both compile, therefore they are both acceptable. Should you do it. No. Acceptablility wasn't the main point of the FAQ. The main point was that one way is recommended. This is not a controversial issue. The OP should not cast malloc. This is definitely not a case that's special enough to require a cast. We should not have any problems agreeing. I think you are doing the OP a disservice by suggesting casting just because it's acceptable. If you cared an ounce, you would suggest that he didn't cast malloc because that's what's best for his code.
    Don't quote me on that... ...seriously

  15. #15
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    I agree with quzah about not changing your coding style so its easier to "convert" to another language. Otherwise you'd see moronic C comments like

    Code:
    int b = 0; // In BASIC: dim b as integer = 0, in PHP: $b = 0... and the moronic list goes on...
    Also in C++ you shouldn't be using malloc, use new and delete!
    Last edited by zacs7; 03-31-2007 at 07:34 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Char array problem.
    By kbro3 in forum C++ Programming
    Replies: 16
    Last Post: 08-21-2008, 01:31 PM
  2. Entering data into array of char pointers
    By richdb in forum C Programming
    Replies: 13
    Last Post: 04-09-2006, 07:30 AM
  3. Problem Putting INTs Into a CHAR Array
    By cram in forum C++ Programming
    Replies: 13
    Last Post: 10-13-2004, 07:53 AM
  4. Passing pointers between functions
    By heygirls_uk in forum C Programming
    Replies: 5
    Last Post: 01-09-2004, 06:58 PM
  5. Creating 2D arrays on heap
    By sundeeptuteja in forum C++ Programming
    Replies: 6
    Last Post: 08-16-2002, 11:44 AM