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
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
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.
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.
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
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/program
Building 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
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.
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"};
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"};
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.
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
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
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 &.
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
Enable Microsoft extensions...
Quote from: Monolith on July 03, 2012, 08:16:27 AM
Enable Microsoft extensions...
What we are telling you is that for a string intializer to work correctly you need space for the trailing 0... you do not get to simply ignore it. The compiler will want to put it there when crunching your code. The result will be a buffer overrun leaving you with unknown contents in at least one section of your struct. Moreover you are removing the trailing 0 safeguard that all strings carry.
If you absolutely insist upon putting single characters --and treating the array as such-- then your use of four separate characters ... '1', '2', '3', '4', "Test" ... from an earlier message is the correct intializer. Although you might be in for a bit of a surprise when you find out it's actually loaded with numerical values 49, 50, 51 and 52, which are the ascii equivalents of the characters you specified.
If you want numerical values in your char array you would use 1, 2, 3, 4, "Test"
If you change c in your struct to an int, the correct intializer is 1234, "Test"
As Ralf points out you are very unwise to ignore the warning... because the result would be that your char c[4] variable would be loaded with '1' followed by whatever garbage was floating around in memory at the time. Your intializer will have failed and almost certainly your program would misbehave in ways that could be next to impossible to troubleshoot.
It's called "undefined behaviour" and C programmers avoid it like the plague.
Quote from: Monolith on July 03, 2012, 07:05:29 AM
This would be perfectly acceptable. However, I wanted to access each byte without >> and/or &.
If you put the value 1234 in an integer, you will not get back 3 by accessing the third byte... Integers store numbers in binary... in this case as...
00000000 00000000 00000100 11010010 (1234 dec)
Accessing the third byte would get you ... 4 and the last byte would get you 210.
Why don't you spend a couple of minutes and tell us what you're trying to do...
Odds are we can help you get it going.
Quote from: CommonTater on July 03, 2012, 12:01:18 PM
Quote from: Monolith on July 03, 2012, 07:05:29 AM
This would be perfectly acceptable. However, I wanted to access each byte without >> and/or &.
If you put the value 1234 in an integer, you will not get back 3 by accessing the third byte... Integers store numbers in binary... in this case as...
00000000 00000000 00000100 11010010 (1234 dec)
Accessing the third byte would get you ... 4 and the last byte would get you 210.
Why don't you spend a couple of minutes and tell us what you're trying to do...
Odds are we can help you get it going.
He is not trying to put the "numeric value" of 1234 but the single characters. This "might" work due to the weak (non-existent) type checking of C, on some compilers at least. But as I mentioned, it's just a side effect, not guaranteed to work on any compiler or any CPU architecture. And bad programming is still bad programming, regardless of what "extensions" are being enabled...
Again, that warning message that Pelle's C is emitting is absolutely to the point and should rather be taken serious than trying to find ways to work around or even call it a compiler bug. As he found out himself, there is a legit way to do what he intended to do...
Ralf
Quote from: Bitbeisser on July 03, 2012, 06:22:40 PM
Again, that warning message that Pelle's C is emitting is absolutely to the point and should rather be taken serious than trying to find ways to work around or even call it a compiler bug. As he found out himself, there is a legit way to do what he intended to do...
As I suggested, turn the warning level all the way up and treat every warning as a problem to be fixed by adjusting source code. This should be SOP at least until the individual understands C well enough to selectively ignore certain warnings... But clearly not this one about bad initializers.
We seem to be going around in circles. I don't need help. I made a mistake in how to initialize a char array. I never wanted a trailing zero. I had no intention of printing the code. When I said you can use an int type, it was only to make my initial initialization work; that was all I meant by that. It doesn't matter if it is bad coding practice or not. That was not the point. And by the way, it is legit to put multiple char in a single quote. It was added to to Pelles C purposely under the Microsoft extensions.
Quote'Multi-byte' character constants are accepted: 'abc' turns into ('a' << 16) | ('b' << 8) | ('c'). [4.00]
That means this would also compile correctly under Pelles C and MSVC without errors and warnings.
Quote from: Monolith on July 03, 2012, 07:13:27 PM
We seem to be going around in circles. I don't need help. I made a mistake in how to initialize a char array. I never wanted a trailing zero. I had no intention of printing the code. When I said you can use an int type, it was only to make my initial initialization work; that was all I meant by that. It doesn't matter if it is bad coding practice or not. That was not the point.
Well, the point is/was that you were very quick to post this as a compiler bug report
QuoteAnd by the way, it is legit to put multiple char in a single quote. It was added to to Pelles C purposely under the Microsoft extensions.
Sorry, but I don't' call this "legit". It's a lame crutch at best. You won't find anything in either K&R or any of the C standards that supports that kind of usage. It will be flagged with a warning in pretty much all compilers that I know and use. And honestly, I stopped using a Microsoft C compiler sometime in the late '80s, that's when they became too "quirky" to allow me to use any source code on any other compiler...
Ralf
Quote from: Monolith on July 03, 2012, 07:13:27 PM
And by the way, it is legit to put multiple char in a single quote. It was added to to Pelles C purposely under the Microsoft extensions.
It's not standard C-99 or C-11 ... it is an
extension added by Microsoft in their own compilers. What that means is that it's not going to compile on any compiler that's not using MS extensions...
Relying on non-standard programming to make your program work isn't exactly the smartest thing to do, especially when there are standardized alternatives already available.
QuoteIt doesn't matter if it is bad coding practice or not. That was not the point.
Actually that's exactly the point Ralf was making... It does matter.
As you learn more about programming you're going to find out why it matters... especially when you find your code is suddenly misbehaving after installing a new version of the compiler.
http://en.wikipedia.org/wiki/Undefined_behavior (http://en.wikipedia.org/wiki/Undefined_behavior)
I never said I was going to use this example. I am well aware what is and is not good coding practice. I was used to being able to set multiple bytes at once. That is where is misconception came from.
I am tired of this forum; please delete my account.
QuoteISO/IEC 9899:201x Committee Draft — April 12, 2011 N1570
32 EXAMPLE 8 The declaration
char s[] = "abc", t[3] = "abc";
defines ''plain'' char array objects s and t whose elements are initialized with character string literals.
This declaration is identical to
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
const struct_t test = {{'1','2','3','4'}, "Test"};