众所周知,如果你像arr[i]在C中那样访问数组元素,你也可以访问元素i[arr],因为这些只是归结为*(arr + i)并且加法是可交换的.我的问题是为什么这适用于大于的数据类型char,因为sizeof(char)是1,而对我来说,这应该只用一个char来推进指针.
也许这个例子让它更清晰:
#include <string.h>
#include <stdio.h>
struct large { char data[1024]; };
int main( int argc, char * argv[] )
{
struct large arr[4];
memset( arr, 0, sizeof( arr ) );
printf( "%lu\n", sizeof( arr ) ); // prints 4096
strcpy( arr[0].data, "should not be accessed (and is not)" );
strcpy( arr[1].data, "Hello world!" );
printf( "%s, %s, %s\n", arr[1].data, 1[arr].data, (*(arr+1)).data );
// prints Hello world!, Hello …Run Code Online (Sandbox Code Playgroud) 我目前正在参加CS107课程,该课程做出以下假设:
sizeof(int) == 4sizeof(short) == 2sizeof(char) == 1我的教授展示了以下代码:
int arr[5];
((short*)(((char*) (&arr[1])) + 8))[3] = 100;
Run Code Online (Sandbox Code Playgroud)
这是代表的20个字节arr:
|....|....|....|....|....|
Run Code Online (Sandbox Code Playgroud)
我的教授&arr[1]在这里指出了一点,我同意这一点.
|....|....|....|....|....|
x
Run Code Online (Sandbox Code Playgroud)
我现在明白,(char*)使指针成为char(1字节)的宽度而不是int的宽度(4字节).
我不明白的是+ 8,我的教授在此指出:
|....|....|....|....|....|
x
Run Code Online (Sandbox Code Playgroud)
但是它不应该指向这里,因为它的前进是char(1字节)大小的8倍?
|....|....|....|....|....|
x
Run Code Online (Sandbox Code Playgroud) 基于这个问题(c中的奇怪输出问题)有一个答案(由@Lundin提供)关于这一行:
int *ptr = (int*)(&a+1);
Run Code Online (Sandbox Code Playgroud)
在哪里他说:
the cast (int*) was hiding this bug.
所以我带来了以下内容:
#include <stdio.h>
int main( void ){
int a[5] = {1,2,3,4,5};
int *ptr = *( ( &a ) + 1 );
printf("%d", *(ptr-1) );
}
Run Code Online (Sandbox Code Playgroud)
我想知道这是否:
int *ptr = *( ( &a ) + 1 );
Run Code Online (Sandbox Code Playgroud)
标准明确定义了吗?
编辑:
在某些时候@chux指出§6.3.2.3.7哪个是:
Run Code Online (Sandbox Code Playgroud)A pointer to an object type may be converted to a pointer to a different object type. If the resulting …
我知道指针算法不允许用于空指针。但想象一下我有这样的事情:
class MyArray {
int *arrayBegin; // pointer to the first array item, NULL for an empty array
unsigned arraySize; // size of the array, zero for an empty array
public:
int *begin() const { return arrayBegin; }
int *end() const { return arrayBegin + arraySize; } // possible? (arrayBegin may be null)
Run Code Online (Sandbox Code Playgroud)
是否有可能(允许)进行上述end()实现?或者是否有必要拥有:
int *end() const { return (arraySize == 0) ? nullptr : (arrayBegin + arraySize); }
Run Code Online (Sandbox Code Playgroud)
避免使用 nullptr 进行指针运算,因为arrayBegin空数组为 null(尽管arraySize在这种情况下也为零)?
我知道可以存储 …
我想检查某种类型的内存对齐T.直截了当的方法是
if (((uintptr_t)&var & __alignof(T) - 1) == 0) ...
Run Code Online (Sandbox Code Playgroud)
但是,uintptr_t它不是现有C++标准的一部分,并且一些编译器不支持它,所以我正在寻找一种可移植的替代方法来实现这一点,std::ptrdiff_t对我来说看起来不错.std::ptrdiff_t保证能够存储两个指针之间的差异,但谁说那些指针之一不能是空指针?在这种情况下std::ptrdiff_t,必须至少与指针本身相同的大小.
template <typename T> bool is_properly_aligned(const T* const ptr)
{
std::ptrdiff_t diff = (ptr - static_cast<T*>(0)) * sizeof(T);
return ((diff & __alignof(T) - 1) == 0);
}
Run Code Online (Sandbox Code Playgroud)
或者那样(摆脱乘法sizeof(T))
template <typename T> bool is_properly_aligned(const T* const ptr)
{
std::ptrdiff_t diff =
reinterpret_cast<const char*>(ptr) - static_cast<const char*>(0);
return ((diff & __alignof(T) - 1) == 0);
}
Run Code Online (Sandbox Code Playgroud)
你怎么看待这种解决方案?它足够便携吗?我没有看到任何原因导致失败,但我想证实.
谢谢.
我正在使用指向结构的指针.我想知道是否可以直接移动到特定位置而不使用++运算符.
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_SIZE 10
struct dummy{
int id;
char buffer[10];
};
typedef struct dummy dummy_struct;
int main()
{
int i=0;
dummy_struct *ds = malloc(sizeof(dummy_struct)*ARRAY_SIZE);
dummy_struct *iterator = ds;
for(i=0;i<ARRAY_SIZE;i++)
{
iterator->id = i;
sprintf(iterator->buffer,"%d",i);
iterator++;
}
iterator = ds;
for(i=0;i<ARRAY_SIZE;i++)
{
printf("%d:%s:%p\n",iterator->id,iterator->buffer,iterator);
iterator++;
}
// I want to access directly to 5th position
iterator = ds + (sizeof(dummy_struct)*5);
printf("5th position %d:%s:%p\n",iterator->id,iterator->buffer,iterator);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个说法
iterator = ds + (sizeof(dummy_struct)*5);
Run Code Online (Sandbox Code Playgroud)
不管用.我将不胜感激任何建议.
我是C新手,但多年来一直是程序员,所以我试图从2008年开始沿着斯坦福大学的课程学习C,并在C.中的向量上做作业3.
它基本上只是一个通用数组,所以数据作为一个结构保存在一个结构中void *.编译器标志-Wpointer-arith打开,所以我不能算术(我明白原因).
数据周围的结构必须不知道数据的类型,因此它对调用者来说是通用的.
为简化起见,我正在尝试以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
void *data;
int aindex;
int elemSize;
} trial;
void init(trial *vector, int elemSize)
{
vector->aindex = 0;
vector->elemSize = elemSize;
vector->data = malloc(10 * elemSize);
}
void add(trial *vector, const void *elemAddr)
{
if (vector->aindex != 0)
vector->data = (char *)vector->data + vector->elemSize;
vector->aindex++;
memcpy(vector->data, elemAddr, sizeof(int));
}
int main()
{
trial vector;
init(&vector, sizeof(int));
for …Run Code Online (Sandbox Code Playgroud) 我想知道它*(&array + 1)是如何工作的.我认为这是一种计算数组长度的简单方法,并希望在使用之前正确理解它.我对指针算法不是很熟悉,但是我的理解 &array给出了数组第一个元素的地址.(&array + 1)会在地址方面转到数组的末尾.但是不应该*(&array + 1)给出这个地址的价值.相反,它打印出地址.我真的很感谢你的帮助,让我的脑袋里的指针清晰.
这是我正在研究的一个简单例子:
int numbers[] = {5,8,9,3,4,6,1};
int length = *(&numbers + 1) - numbers;
Run Code Online (Sandbox Code Playgroud) 假设我们有:
char* a;
int i;
Run Code Online (Sandbox Code Playgroud)
许多引入到C++(像这样一个)表明,右值a+i和&a[i]可以互换.我天真地相信这几十年,直到我最近偶然发现了[dcl.ref]引用的以下文字(这里):
特别是,空引用不能存在于定义良好的程序中,因为创建这样的引用的唯一方法是将它绑定到通过解引用空指针获得的"对象",这会导致未定义的行为.
换句话说,将引用对象"绑定"到空取消引用会导致未定义的行为.基于上述文本的上下文,可以推断仅仅评估 &a[i](在offsetof宏内)被认为是"约束"参考.此外,似乎存在共识,&a[i]导致在a=null和的情况下出现未定义的行为i=0.这种行为不同于a+i(至少在C++中,在a = null,i = 0的情况下).
这导致约之间的差异至少2个问题a+i和&a[i]:
首先,是什么底层之间的语义差别a+i以及&a[i]导致这种行为差异.是否可以根据任何类型的一般原则来解释,而不仅仅是"绑定对空取消引用对象的引用会导致未定义的行为,因为这是一个每个人都知道的特定情况"?是否&a[i]可以生成内存访问a[i]?或者规范作者对那天的空引用不满意?或者是其他东西?
其次,除了情况a=null及i=0,是否有任何其他地方的情况a+i和&a[i]不同的表现?(第一个问题可以涵盖,取决于答案.)
据说在 C 中,当指针指向同一个数组或该数组末尾之后的一个元素时,算术和比较是明确定义的。那么数组第一个元素之前的一个呢?只要我不取消引用就可以了吗?
给定的
int a[10], *p;
p = a;
Run Code Online (Sandbox Code Playgroud)
(1) 写字合法--p吗?
(2)p-1在表达式中写入是否合法?
(3) 如果 (2) 没问题,我可以断言p-1 < a吗?
对此有一些实际的担忧。考虑一个reverse()函数,它反转以 结尾的 C 字符串'\0'。
#include <stdio.h>
void reverse(char *p)
{
char *b, t;
b = p;
while (*p != '\0')
p++;
if (p == b) /* Do I really need */
return; /* these two lines? */
for (p--; b < p; b++, p--)
t = *b, *b = *p, *p …Run Code Online (Sandbox Code Playgroud)