- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
更新2020-12-11:感谢@“某些程序员老兄”的意见。
我的根本问题是我们的团队正在实现动态类型的存储引擎。我们分配了多个char数组[PAGE_SIZE]缓冲区,它们的和16对齐的用于存储动态类型的数据(没有固定的结构)。出于效率原因,我们无法执行字节编码或分配额外的空间来使用memcpy
。
由于已经确定了对齐方式(即16),剩下的就是使用指针的类型转换来访问指定类型的对象,例如:
int main() {
// simulate our 16-aligned malloc
_Alignas(16) char buf[4096];
// store some dynamic data:
*((unsigned long *) buf) = 0xff07;
*(((double *) buf) + 2) = 1.618;
}
但是我们的团队对此操作是否为未定义行为表示怀疑。
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned 68) for the referenced type, the behavior is undefined.
68) In general, the concept ‘‘correctly aligned’’ is transitive: if a pointer to type A is correctly aligned for a pointer to type B, which in turn is correctly aligned for a pointer to type C, then a pointer to type A is correctly aligned for a pointer to type C.
此处的 结果指针是指 指针对象还是 指针值?
我认为答案是 指针对象,但是更多答案似乎表明 指针值。
解释A:指针对象
我的想法如下:指针本身就是一个对象。根据 6.2.5 #28,不同的指针可能具有不同的表示形式和对齐要求。因此,根据 6.3.2.3 #7,只要两个指针具有相同的对齐方式,就可以安全地转换它们而没有未定义的行为,但是不能保证可以将它们取消引用。
在程序中表达这个想法:#include <stdio.h>
int main() {
char buf[4096];
char *pc = buf;
if (_Alignof(char *) == _Alignof(int *)) {
// cast safely, because they have the same alignment requirement?
int *pi = (int *) pc;
printf("pi: %p\n", pi);
} else {
printf("char * and int * don't have the same alignment.\n");
}
}
解释B:指针值
但是,如果C11标准讨论的是引用类型的 指针值,而不是 指针对象。上面代码的对齐检查是没有意义的。
在程序中表达这个想法:#include <stdio.h>
int main() {
char buf[4096];
char *pc = buf;
/*
* undefined behavior, because:
* align of char is 1
* align of int is 4
*
* and we don't know whether the `value` of pc is 4-aligned.
*/
int *pi = (int *) pc;
printf("pi: %p\n", pi);
}
哪种解释是正确的?
最佳答案
解释B是正确的。该标准谈论的是指向对象的指针,而不是对象本身。 “结果指针”指的是强制类型转换的结果,并且强制类型转换不会产生左值,因此它是指强制类型转换之后的指针值。
以您示例中的代码为例,假设int
必须在4字节边界上对齐,即它的地址必须是4的倍数。如果buf
的地址是0x1001
,则将该地址转换为int *
是无效的,因为指针值为排列不正确。如果buf
的地址是0x1000
,则将其转换为int *
是有效的。
更新:
您添加的代码解决了对齐问题,因此在这方面很好。但是,它有一个不同的问题:它违反了严格的别名。
您定义的数组包含char
类型的对象。通过将地址强制转换为其他类型,然后取消引用转换后的类型类型,可以将一种类型的对象作为另一种类型的对象进行访问。 C标准不允许这样做。
尽管标准中未使用“严格混叠”一词,但在6.5节第6和第7段中描述了该概念:
6 The effective type of an object for an access to its stored value is the declared type of the object, if any.87) If avalue is stored into an object having no declared type through anlvalue having a type that is not a character type, then the type ofthe lvalue becomes the effective type of the object for that accessand for subsequent accesses that do not modify the stored value. If avalue is copied into an object having no declared type using
memcpy
ormemmove
, or is copied as an array of character type, then theeffective type of the modified object for that access and forsubsequent accesses that do not modify the value is the effective typeof the object from which the value is copied, if it has one. For allother accesses to an object having no declared type, the effectivetype of the object is simply the type of the lvalue used for theaccess.7 An object shall have its stored value accessed only by an lvalue expression that has one of the following types:88)
- a type compatible with the effective type of the object,
- a qualified version of a type compatible with the effective type of the object,
- a type that is the signed or unsigned type corresponding to the effective type of the object,
- a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of asubaggregate or contained union), or
- a character type.
...
87 ) Allocated objects have no declared type.
88 ) The intent of this list is to specify those circumstances in whichan object may or may not be aliased.
unsigned long
对象的顶部编写一个
double
和
char
。这些类型都不满足第7段的条件。
*(((double *) buf) + 2) = 1.618;
当您将
buf
视为不是
double
的数组时,会将其视为。至少,您将需要直接对
buf
执行必要的算术并将结果强制转换为最后。
char
数组而不是
malloc
返回的缓冲区的问题?因为从
malloc
返回的内存没有有效的类型,除非您在其中存储了内容,这就是第6段和脚注87所描述的。
-fno-strict-aliasing
标志
关于C-两个指针之间的转换行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65240303/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
指针, C语言的精髓 莫队先咕几天, 容我先讲完树剖 (因为后面树上的东西好多都要用树剖求 LCA). 什么是指针 保存变量地址的变量叫做指针. 这是大概的定义, 但是Defad认为
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我是一名优秀的程序员,十分优秀!