Char Pointer After Char Array

Started by Monolith, July 02, 2012, 03:32:01 AM

Previous topic - Next topic

Monolith

When putting a char pointer after a char array in a structure the expected char pointer type is char array.
Example:

typedef struct struct_t {
    char c[4];
    char *s;
} struct_t;

const struct_t test = {'1234', "Test"}; // <------- Compiler complains expecting 'char' but found 'char *'


Pelles C Version: 7 RC4

Bitbeisser

Seems more like a user error than a bug in Pelle's C...

You should actually get a warning 2055 before that error message you mentioned and that warning is a direct hint as to what you did wrong...

Ralf

CommonTater

Also take note that in order to correctly store "1234" you need 5 characters not 4 in your c array... one for each of the characters and one for the trailing 0.


Monolith

Oops, my bad. I don't know what you guys were saying, for that code I didn't get an error message 2055 and I used single quotes not double. Anyway, I have been programming in asm lately and I made a error in what you can set in single quote in C.

Bitbeisser

Quote from: CommonTater on July 02, 2012, 05:04:38 AM
Also take note that in order to correctly store "1234" you need 5 characters not 4 in your c array... one for each of the characters and one for the trailing 0.
Well, that's part of what the warning message that I mentioned would lead him too...  ;)

This is more a beginners question/issue than a compiler bug, courtesy of the "nice"  string handling capabilities of C (or better, the lack thereof)

Ralf

Bitbeisser

#5
Quote from: Monolith on July 02, 2012, 05:35:19 AM
Oops, my bad. I don't know what you guys were saying, for that code I didn't get an error message 2055 and I used single quotes not double. Anyway, I have been programming in asm lately and I made a error in what you can set in single quote in C.
It's not a "error" 2055, but a "warning". I suspect you have warnings disabled to not be bothered, though they are giving hints to improper programming.

Using double quotes alone isn't fixing the problem, you still need to increase the size of the array in that case in order to accommodate the terminating '/0' character...

Here's both the warning and the error message as they show up when put into a simple test project/programBuilding C:\Documents and Settings\Ralf\My Documents\Pelles C Projects\monolith\output\monolith.obj.
C:\Documents and Settings\Ralf\My Documents\Pelles C Projects\monolith\monolith.c(6): warning #2055: Excess characters in 'char' character literal ignored.
C:\Documents and Settings\Ralf\My Documents\Pelles C Projects\monolith\monolith.c(6): error #2082: Invalid initialization type; expected 'char' but found 'char *'.

Ralf

CommonTater

#6
Quote from: Monolith on July 02, 2012, 05:35:19 AM
Oops, my bad. I don't know what you guys were saying, for that code I didn't get an error message 2055 and I used single quotes not double.

A suggestion...
Go into Project -> Project Options -> Compiler -> Warnings = Level 2
Make the report pane at the bottom of the IDE a bit bigger.

Now treat each warning as an error... something to be fixed.

The lesson is...  "Compiles" does not mean "Works".


Quote
Anyway, I have been programming in asm lately and I made a error in what you can set in single quote in C.

An ASM programmer should be keenly aware of the trailing 0 on every string, since he would most often have to put them there manually. 


Monolith

Again, I am aware of the trailing zeros, that is why I used single quotes, not double. So I will not receive that warning message. In asm you can set all the fields at once, in C you cannot.
The correction would be:

const struct_t test = {'1','2','3','4',"Test"};

CommonTater

#8
Quote from: Monolith on July 02, 2012, 07:31:42 PM
Again, I am aware of the trailing zeros, that is why I used single quotes, not double. So I will not receive that warning message. In asm you can set all the fields at once, in C you cannot.
The correction would be:

const struct_t test = {'1','2','3','4',"Test"};


The thing is that you should want that trailing 0 in there.  It terminates the string so any of the string functions don't just run on and fill your screen with garbage when reading it.  C has no way to know the actual length of a string in advance and is totally dependent on that trailing 0 to know when to stop.  I've seen unterminated strings result in screen after screen of junk as puts() (etc.) runs on and on looking for that 0.

Your code sould say...

typedef struct struct_t {
    char c[5];
    char *s;
} struct_t;

const struct_t test = {"1234", "Test"};

Monolith

Yes, a zero trail is needed to print strings; however, I never intended to print the string. Each of those char would have represented a byte of information, i.e. 'E' = perform "E" procedure. You could also think of it as using int8_t or uint8_t type.

Bitbeisser

Quote from: Monolith on July 02, 2012, 07:31:42 PM
Again, I am aware of the trailing zeros, that is why I used single quotes, not double. So I will not receive that warning message.
Well, that is exactly the reason why you should receive that warning message!

Single quotes are for single characters only! Character arrays would use double quotes and then also require a trailing '\0' when writing them as constants...
QuoteIn asm you can set all the fields at once, in C you cannot.
Correct, as assembler just treats them as single bytes, C is more "advanced" here and assumes proper string handling....
QuoteThe correction would be:

const struct_t test = {'1','2','3','4',"Test"};
Depending on what you intended purpose is/was (and which isn't obvious by just teh snippet you posted), that would be indeed the correct way to so this....

Ralf

Bitbeisser

Quote from: CommonTater on July 03, 2012, 02:45:29 AM
The thing is that you should want that trailing 0 in there.
Well, no, not necessarily. You can use the four characters in the array just by them self, if you know that you have an array of fixed length and do not use them for any "string" purposes.

But as I mentioned in my previous post, his intention where less than obvious from just the posted snippet...

Ralf

Monolith

Quote from: Bitbeisser on July 03, 2012, 05:35:46 AM
Single quotes are for single characters only! Character arrays would use double quotes and then also require a trailing '\0' when writing them as constants...

Single quotes can be for multiple characters, for example if I wrote:


typedef struct struct_t {
    int c;
    char *s;
} struct_t;

static struct_t test = {'1234', "Test"};


This would be perfectly acceptable. However, I wanted to access each byte without >> and/or &.

Bitbeisser

Quote from: Monolith on July 03, 2012, 07:05:29 AM
Quote from: Bitbeisser on July 03, 2012, 05:35:46 AM
Single quotes are for single characters only! Character arrays would use double quotes and then also require a trailing '\0' when writing them as constants...

Single quotes can be for multiple characters, for example if I wrote:


typedef struct struct_t {
    int c;
    char *s;
} struct_t;

static struct_t test = {'1234', "Test"};


This would be perfectly acceptable. However, I wanted to access each byte without >> and/or &.
Sorry, but no, this is not correct.

Single quotes are for single characters only! For the above, with warnings enabled, you get the very same warning message warning #2055: Excess characters in 'char' character literal ignored.And that warning tells you exactly what is wrong. You have "excess characters", it can't be much clearer.

That with warnings disabled the above code might compile and run does not change the fact that this is very bad code, simply relying on the side effects that allow this to 'look like working'. If you try this on a processor with a different endian and/or a larger default int (64bit), this code will fail!

Ralf

Monolith