取消类型的指针将打破严格的别名规则。

时间:2021-10-04 12:59:44

I have a unsigned char pointer which contains a structure.Now I want to do the following

我有一个无符号的char指针,它包含一个结构。下面我要做的是。

unsigned char buffer[24];

//code to fill the buffer with the relevant information.

int len = ntohs((record_t*)buffer->len);

where record_t structure contains a field called len.I am not able to do so and am getting the error.

其中record_t结构包含一个名为len的字段。我不能这样做,而且我正在犯错误。

error: request for member ‘len’ in something not a structure or union.

Then I tried:

然后我试着:

int len = ntohs(((record_t*)buffer)->len);

so as to get the operator precedence right. That gave me the warning: dereferencing type-punned pointer will break strict-aliasing rules.

从而得到运算符的优先级。这给了我一个警告:取消类型的指针将打破严格的别名规则。

then I declared

那么我宣布

record_t *rec = null;

rec = (record_t*)

what am I doing wrong here?

我在这里做错了什么?

4 个解决方案

#1


19  

According to the C and C++ standards, it is undefined behaviour to access a variable of a given type through a pointer to another type. Example:

根据C和c++标准,通过指向另一类型的指针访问给定类型的变量是未定义的行为。例子:

int a;
float * p = (float*)&a;  // #1
float b = *p;            // #2

Here #2 causes undefined behaviour. The assignment at #1 is called "type punning". The term "aliasing" refers to the idea that several different pointer variables may be pointing at the same data -- in this case, p aliases the data a. Legal aliasing is a problem for optimization (which is one of the main reasons for Fortran's superior performance in certain situations), but what we have here is flat-out illegal aliasing.

这里#2导致了未定义的行为。在#1的作业被称为“类型双关”。“混叠”一词指的是几种不同的指针变量可能指向相同的数据——在本例中,p别名数据。法律混叠问题优化的主要原因之一(这是Fortran的优越性能在某些情况下),但是我们是完全非法的混叠。

Your situation is no different; you're accessing data at buffer through a pointer to a different type (i.e. a pointer that isn't char *). This is simply not allowed.

你的情况没有什么不同;通过指向不同类型的指针(即不是char *的指针)访问缓冲区中的数据。这是不允许的。

The upshot is: You should never have had data at buffer in the first place.

其结果是:首先,您不应该在缓冲区中有数据。

But how to solve it? Make sure you have a valid pointer! There is one exception to type punning, namely accessing data through a pointer to char, which is allowed. So we can write this:

但是如何解决呢?确保你有一个有效的指针!有一个例外,即通过一个指向char的指针访问数据,这是允许的。所以我们可以这样写:

record_t data;
record_t * p = &data;          // good pointer
char * buffer = (char*)&data;  // this is allowed!

return p->len;                 // access through correct pointer!

The crucial difference is that we store the real data in a variable of the correct type, and only after having allocated that variable do we treat the variable as an array of chars (which is allowed). The moral here is that the character array always comes second, and the real data type comes first.

关键的区别在于,我们将实际数据存储在正确类型的变量中,并且只有在分配了该变量之后,我们才会将变量视为一个字符数组(这是允许的)。这里的寓意是,字符数组总是排在第二位,而真正的数据类型是首先出现的。

#2


5  

You're getting that warning because you're breaking strict-aliasing by having two pointers of different types pointing to the same location.

你得到那个警告,因为你正在打破严格的混叠,有两个不同类型的指针指向同一个位置。

One way to get around that is to use unions:

解决这个问题的方法之一是使用工会:

union{
    unsigned char buffer[24];
    record_t record_part;
};

//code to fill the buffer with the relavent information.

int len = ntohs(record_part.len);

EDIT:

编辑:

Strictly speaking, this isn't much safer than your original code, but it doesn't violate strict-aliasing.

严格地说,这并不比您的原始代码安全得多,但是它并没有违反严格的别名。

#3


3  

You might try this:

您可以试一试这个:

unsigned char buffer[sizeof(record_t)];
record_t rec;
int len;

// code to fill in buffer goes here...

memcpy(&rec, buffer, sizeof(rec));
len = ntohs(rec.len);

#4


0  

You probably have a warning level set that includes strict aliasing warnings (it used to not be default, but at one point gcc flipped the default). try -Wno-strict-aliasing or -fno-strict-aliasing -- then gcc should not generate the warnings

您可能有一个警告级别设置,其中包括严格的别名警告(它以前不是默认的,但是在某个时候gcc会抛出默认值)。尝试- wno -strict- ali或-fno-strict-aliasing——然后gcc不应该生成警告。

A reasonably good explanation (based on cursory glance) is What is the strict aliasing rule?

一个合理的解释(粗略的看一下)是什么是严格的混叠规则?

#1


19  

According to the C and C++ standards, it is undefined behaviour to access a variable of a given type through a pointer to another type. Example:

根据C和c++标准,通过指向另一类型的指针访问给定类型的变量是未定义的行为。例子:

int a;
float * p = (float*)&a;  // #1
float b = *p;            // #2

Here #2 causes undefined behaviour. The assignment at #1 is called "type punning". The term "aliasing" refers to the idea that several different pointer variables may be pointing at the same data -- in this case, p aliases the data a. Legal aliasing is a problem for optimization (which is one of the main reasons for Fortran's superior performance in certain situations), but what we have here is flat-out illegal aliasing.

这里#2导致了未定义的行为。在#1的作业被称为“类型双关”。“混叠”一词指的是几种不同的指针变量可能指向相同的数据——在本例中,p别名数据。法律混叠问题优化的主要原因之一(这是Fortran的优越性能在某些情况下),但是我们是完全非法的混叠。

Your situation is no different; you're accessing data at buffer through a pointer to a different type (i.e. a pointer that isn't char *). This is simply not allowed.

你的情况没有什么不同;通过指向不同类型的指针(即不是char *的指针)访问缓冲区中的数据。这是不允许的。

The upshot is: You should never have had data at buffer in the first place.

其结果是:首先,您不应该在缓冲区中有数据。

But how to solve it? Make sure you have a valid pointer! There is one exception to type punning, namely accessing data through a pointer to char, which is allowed. So we can write this:

但是如何解决呢?确保你有一个有效的指针!有一个例外,即通过一个指向char的指针访问数据,这是允许的。所以我们可以这样写:

record_t data;
record_t * p = &data;          // good pointer
char * buffer = (char*)&data;  // this is allowed!

return p->len;                 // access through correct pointer!

The crucial difference is that we store the real data in a variable of the correct type, and only after having allocated that variable do we treat the variable as an array of chars (which is allowed). The moral here is that the character array always comes second, and the real data type comes first.

关键的区别在于,我们将实际数据存储在正确类型的变量中,并且只有在分配了该变量之后,我们才会将变量视为一个字符数组(这是允许的)。这里的寓意是,字符数组总是排在第二位,而真正的数据类型是首先出现的。

#2


5  

You're getting that warning because you're breaking strict-aliasing by having two pointers of different types pointing to the same location.

你得到那个警告,因为你正在打破严格的混叠,有两个不同类型的指针指向同一个位置。

One way to get around that is to use unions:

解决这个问题的方法之一是使用工会:

union{
    unsigned char buffer[24];
    record_t record_part;
};

//code to fill the buffer with the relavent information.

int len = ntohs(record_part.len);

EDIT:

编辑:

Strictly speaking, this isn't much safer than your original code, but it doesn't violate strict-aliasing.

严格地说,这并不比您的原始代码安全得多,但是它并没有违反严格的别名。

#3


3  

You might try this:

您可以试一试这个:

unsigned char buffer[sizeof(record_t)];
record_t rec;
int len;

// code to fill in buffer goes here...

memcpy(&rec, buffer, sizeof(rec));
len = ntohs(rec.len);

#4


0  

You probably have a warning level set that includes strict aliasing warnings (it used to not be default, but at one point gcc flipped the default). try -Wno-strict-aliasing or -fno-strict-aliasing -- then gcc should not generate the warnings

您可能有一个警告级别设置,其中包括严格的别名警告(它以前不是默认的,但是在某个时候gcc会抛出默认值)。尝试- wno -strict- ali或-fno-strict-aliasing——然后gcc不应该生成警告。

A reasonably good explanation (based on cursory glance) is What is the strict aliasing rule?

一个合理的解释(粗略的看一下)是什么是严格的混叠规则?