标签: pointer-arithmetic

关于指针的算术是关联的吗?

如果我说,

int a[] = {1, 2, 3, 4, 5};
int *p = a;
Run Code Online (Sandbox Code Playgroud)

现在,如果我写的话p + 1 + 2会和它一样((p + 1) + 2)吗?任何证明这个错误的标准参考?

c++ pointers pointer-arithmetic

7
推荐指数
1
解决办法
288
查看次数

C分数算术

对于我需要做的以下事情,我遇到了很大的困难:
a.声明包含有理数的数据结构.
写f'xns将+, - ,*,/有理数.
所有f'xns必须传递3个参数,每个参数指向在a部分中声明的类型I的数据结构; 2个参数=操作数,第3个=结果.
C.编写一个f'xn,它将指向数据结构的指针作为参数,并返回数字的GCD.&denom.
d.使用c部分中的f'xn来编写一个将分数(有理数)减少到最低项的f'xn.传入指向分数的指针,并用f'xn修改分数.
写入输入和输出功能,以便用户可以以1/5的形式输入分数.

应允许用户输入任意数量的问题,程序应以最低的条件输出答案.

我是在正确的轨道上吗?我相信我有下降,但不是d,尤其是e.有人可以指导我或帮我纠正我的剧本吗?

int GCD (int numer, int denom)
{
    int result;
    while (denom > 0) {
        result = numer % denom;
        numer = denom;
        denom = result;
    }
    return numer;
}

int getLCM (int numer, int denom)
{
    int max;
    max = (numer > denom) ? numer : denom;
    while (1) {
        if (max % numer == 0 && max % denom == 0)
            break; …
Run Code Online (Sandbox Code Playgroud)

c struct rational-numbers pointer-arithmetic fractions

7
推荐指数
1
解决办法
4334
查看次数

为什么在offsetof()中减去空指针?

Linux的stddef.h定义offsetof()为:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
Run Code Online (Sandbox Code Playgroud)

而维基百科上的文章offsetof()(http://en.wikipedia.org/wiki/Offsetof)将其定义为:

#define offsetof(st, m) \
    ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))
Run Code Online (Sandbox Code Playgroud)

为什么减去(char *)0维基百科版本?有什么情况会真正有所作为吗?

c offsetof pointer-arithmetic

6
推荐指数
1
解决办法
1079
查看次数

在C中明显的NULL指针取消引用实际上是指针算术吗?

我有这段代码.它似乎在这里取消引用空指针,但随后按位与结果和unsigned int.我真的不明白整个部分.它打算做什么?这是指针算术的一种形式吗?

struct hi  
{
   long a;  
   int b;  
   long c;  
};  

int main()  
{  
    struct hi ob={3,4,5};  
    struct hi *ptr=&ob;  
    int num= (unsigned int) & (((struct hi *)0)->b);  

   printf("%d",num);  
   printf("%d",*(int *)((char *)ptr + (unsigned int) & (((struct hi *)0)->b)));  
}  
Run Code Online (Sandbox Code Playgroud)

我得到的输出是44.但它是如何工作的?

c struct offsetof pointer-arithmetic null-pointer

6
推荐指数
3
解决办法
1298
查看次数

在C中,我应该被允许使用指向不完整类型数组的指针吗?

IAR Embedded C编译器对此很满意,我认为它是正确的C代码:

struct incomplete;
typedef struct incomplete (*why_not)[2];
struct incomplete {struct incomplete *known_to_work;} array[2];
why_not ok = &array;
Run Code Online (Sandbox Code Playgroud)

但是,gcc和clang choke对定义why_not:

incomplete.c:2:29: error: array type has incomplete element type ‘struct incomplete’
 typedef struct incomplete (*why_not)[2];
                             ^
Run Code Online (Sandbox Code Playgroud)

从技术上讲,没有理由拒绝"指向不完整数组的指针"的定义.毕竟,只有在取消引用这样的变量或执行某些指针算术时才需要结构定义.

我渴望在可能的情况下隐藏结构定义.

C标准对此有何看法?

c arrays pointers pointer-arithmetic incomplete-type

6
推荐指数
2
解决办法
260
查看次数

如何明智地解释这个编译器警告?

当我执行这个问题的代码时,我得到了这个警告:

warning: format '%d' expects argument of type 'int', but argument 2 has type 'long int' [-Wformat=]
printf("P-Q: %d, P: %d, Q: %d", (p - q), p, q);
             ~^                 ~~~~~~~
             %ld
Run Code Online (Sandbox Code Playgroud)

作为反射修复,我曾经%ld打印过两个指针的减法.编制者同意了.

幸运的是,我看到其他用户提到%td应该使用的评论,因为减法的结果类型是ptrdiff_t.这个答案证实了这一说法.

现在从GCC的stddef.h头文件中,我可以看到这些类型在这种情况下是等价的:

typedef __PTRDIFF_TYPE__ ptrdiff_t;
#define __PTRDIFF_TYPE__ long int
Run Code Online (Sandbox Code Playgroud)

但是,我只是建议对OP进行错误的(或多或少)修复%ld,而不是%td.

有没有一种方法我可以理解单独的编译器警告是不够的?或者也许明智地解释警告本身,而不仅仅是反应.

c types pointers compiler-warnings pointer-arithmetic

6
推荐指数
1
解决办法
142
查看次数

在动态分配的内存上使用指针算法的未定义行为

我可能误解了这一点,但是 c99 规范是否阻止对动态分配的内存进行任何形式的指针运算?

从 6.5.6p7...

对于这些运算符而言,指向不是数组元素的对象的指针的行为与指向长度为 1 的数组的第一个元素的指针的行为相同,该数组的元素类型为对象的类型。

...指向不在数组中的对象的指针被视为指向包含 1 个项目的数组(使用运算符 + 和 - 时)。然后在这个片段中:

char *make_array (void) {
    char *p = malloc(2*sizeof(*p));
    p[0] = 1; // valid
    p[1] = 2; // invalid ?
    return p;
}
Run Code Online (Sandbox Code Playgroud)

...第二个下标p[1]无效?由于p指向不在数组中的对象,因此它被视为指向一个项目的数组中的对象,然后从 6.5.6p8...

当具有整数类型的表达式与指针相加或相减时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向与原始元素的元素偏移量,使得结果和原始数组元素的下标之差等于整数表达式。换句话说,如果表达式 P 指向数组对象的第 i 个元素,则表达式 (P)+N(等价于 N+(P))和 (P)-N(其中 N 的值为 n)指向分别指向数组对象的第 i+n 个和第 i?n 个元素,前提是它们存在。此外,如果表达式 P 指向数组对象的最后一个元素,则表达式 (P)+1 指向数组对象的最后一个元素,如果表达式 Q 指向数组对象的最后一个元素,则表达式 (Q)-1 指向数组对象的最后一个元素。如果指针操作数和结果都指向同一个数组对象的元素,或者数组对象的最后一个元素之后,求值不会产生溢出;否则,行为未定义。如果结果指向数组对象的最后一个元素,则不应将其用作被评估的一元 * 运算符的操作数。

...我们有未定义的行为,因为我们取消了数组边界(暗示长度为 1 的边界)。

编辑:

好的,为了进一步澄清让我感到困惑的内容,让我们一步一步来:

1.)p[1]定义为*(p+1).
2.)p …

c c99 pointer-arithmetic language-lawyer

6
推荐指数
1
解决办法
263
查看次数

您能否在此程序中解释array + 5的目的?

我了解它的大部分工作原理,除了main函数中的第二行:int* end = array+5;。那条线是如何工作的?

#inlcude <iostream>
int main()
{
    int array[] = {10, 20, 29, 200, 2};

    int* end = array+5;
    for(int* it = array; it != end; ++it)
    {
        std::cout << *it << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

应该只打印列表中的每个元素。

c++ arrays pointer-arithmetic

6
推荐指数
2
解决办法
168
查看次数

malloc 块是否允许指针算术?

我正在阅读 C 标准中的以下内容:

(6.5.6 加法运算符)

9 当两个指针相减时,两个指针都指向同一个数组对象的元素,或者指向数组对象最后一个元素之后的一个;结果是两个数组元素的下标之差。

现在我想知道什么被认为是“数组对象”。更具体地说,我想知道下面这个愚蠢的例子是否合法?该分配的内存块是否被视为一个“数组对象”?

uint8_t *data = malloc(255);
uint8_t *end = data + 255;
ptrdiff_t size = end - data;
Run Code Online (Sandbox Code Playgroud)

c pointers pointer-arithmetic language-lawyer

6
推荐指数
2
解决办法
507
查看次数

在特定实现上定义了两个数组之间的指针差异吗?

根据C标准:

当两个指针相减时,两者都应指向同一数组对象的元素,或指向数组对象最后一个元素的元素(第 6.5.6 1173 节)

[注意:不要假设我对标准或 UB 了解很多,我只是碰巧发现了这个]

  1. 我知道在几乎所有情况下,无论如何取两个不同数组中指针的差异都是一个坏主意。
  2. 我也知道在某些架构上(我在某处读到的“分段机器”),行为未定义有充分的理由。

现在另一方面

  1. 它在某些极端情况下可能有用。例如,在这篇文章中,它将允许使用具有不同数组的库接口,而不是复制一个数组中的所有内容,然后将其拆分。
  2. 似乎在“普通”架构上,“所有对象都存储在一个大数组中,从大约 0 开始到大约内存大小”的思维方式是对内存的合理描述。当您实际查看不同数组的指针差异时,您会得到合理的结果。

因此我的问题是:从实验来看,似乎在某些体系结构(例如 x86-64)上,两个数组之间的指针差异提供了合理的、可重现的结果。它似乎与这些架构的硬件相当吻合。那么某些实现是否真的确保了特定的行为?

例如,在野外是否有一个实现可以保证a并且b存在char*,我们有a + (reinterpret_cast<std::ptrdiff_t>(b)-reinterpret_cast<std::ptrdiff_t>(a)) == b

c c++ pointer-arithmetic language-lawyer

6
推荐指数
3
解决办法
257
查看次数