Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meanings of parentheses in C++ and C

Tags:

c++

c

I just had a nasty bug in C++. So I had list of registers and values, that are wrapped in a struct and then those structs are initialized in an array. But then I accidentally typed () instead of {}. Here is some test code:

#include <stdio.h>

struct reg_val {
        unsigned reg;
        unsigned val;
};

struct reg_val faulty_array[] = { 
        {0x5001, 0xff},
        {0x5580, 0x01},
        (0x5580, 0x02), //<- THIS LINE IS THE PROBLEM
        (0x5589, 0x00), //<- AND THIS LINE
};

struct reg_val good_array[] = { 
        {0x5001, 0xff}, 
        {0x5580, 0x01}, 
        {0x5580, 0x02},
        {0x5589, 0x00},
};

int main()
{
        unsigned i;
        unsigned faulty_size = sizeof(faulty_array) / sizeof(struct reg_val);
        printf("Size of faulty array: %d\n", faulty_size);

        for (i = 0; i < faulty_size; ++i) {
                printf("faulty reg: %x  val: %x\n", faulty_array[i].reg,
                       faulty_array[i].val);
        }   

        unsigned good_size = sizeof(good_array) / sizeof(struct reg_val);
        printf("\nSize of good array: %d\n", good_size);
        for (i = 0; i < good_size; ++i) {
                printf("good reg: %x  val: %x\n", good_array[i].reg,
                       good_array[i].val);
        }   
        return 0;
}

I am more familiar with C and to my surprise this still compiled with g++:

$ g++ -Wall array.cc
array.cc:11: warning: left-hand operand of comma has no effect
array.cc:12: warning: left-hand operand of comma has no effect
array.cc:13: warning: missing braces around initializer for ‘reg_val’
$ ./a.out 
Size of faulty array: 3
faulty reg: 5001  val: ff
faulty reg: 5580  val: 1
faulty reg: 2  val: 0       <-- the first value gets discarded as mentioned in the compiler warning

Size of good array: 4
good reg: 5001  val: ff
good reg: 5580  val: 1
good reg: 5580  val: 2
good reg: 5589  val: 0

This code would obviously fail to compile with a C compiler, what's the difference in C++ that makes a C++ compiler (although grudgingly) accept this code?

like image 693
Lucas Avatar asked Jul 19 '12 16:07

Lucas


2 Answers

To answer your question, I will first answer: Why does this fail to compile in C? Well, it fails to compile due to:

initializer element is not constant

For good measure, let's drop the {}s from C:

struct reg_val faulty_array[] = { 
        {0x5001, 0xff},
        {0x5580, 0x01},
        0x5580, 0x02, //<- THIS LINE IS THE PROBLEM
        0x5589, 0x00, //<- AND THIS LINE
};

Now the program outputs:

Size of faulty array: 4
faulty reg: 5001  val: ff
faulty reg: 5580  val: 1
faulty reg: 5580  val: 2
faulty reg: 5589  val: 0

This is perfectly allowed by the C standard (and C++). C (and C++) flatten braces to initialize elements of structures (this will come back). Your code fails in C because objects with static storage duration must initialized with constant expressions or with aggregate initializers containing constant expressions. C does not treat (0x5580, 0x02) as a constant expression.

This (unhappily) compiles in C++ because C++ treats the comma operator between two constant expressions as a constant expression, so your code is more like:

struct reg_val faulty_array[] = { 
        {0x5001, 0xff},
        {0x5580, 0x01},
        0x02,
        0x00,
};

...which is, of course, allowed.

struct reg_val faulty_array[] = { 
        {0x5001, 0xff},
        {0x5580, 0x01},
        {0x02, 0x00},
};
like image 102
Travis Gockel Avatar answered Oct 03 '22 00:10

Travis Gockel


What makes you think it would fail to compile in C?

C++: http://ideone.com/KLPh4 C: http://ideone.com/VYUbL

Pay attention to your warnings. I can't stress this enough. Warnings are there to help you catch mistakes like this.

Well, the error message in C makes the difference perfectly clear: C requires the initializers to be constants, not arbitrary expressions. It makes no sense to me why those aren't considered constants, since this compiles fine in C:

  • http://ideone.com/p5I1d
like image 22
Ben Voigt Avatar answered Oct 02 '22 23:10

Ben Voigt