如果我说,
int a[] = {1, 2, 3, 4, 5};
int *p = a;
Run Code Online (Sandbox Code Playgroud)
现在,如果我写的话p + 1 + 2会和它一样((p + 1) + 2)吗?任何证明这个错误的标准参考?
对于我需要做的以下事情,我遇到了很大的困难:
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) 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维基百科版本?有什么情况会真正有所作为吗?
我有这段代码.它似乎在这里取消引用空指针,但随后按位与结果和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.但它是如何工作的?
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标准对此有何看法?
当我执行这个问题的代码时,我得到了这个警告:
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.
有没有一种方法我可以理解单独的编译器警告是不够的?或者也许明智地解释警告本身,而不仅仅是反应.
我可能误解了这一点,但是 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 …
我了解它的大部分工作原理,除了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 标准中的以下内容:
(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标准:
当两个指针相减时,两者都应指向同一数组对象的元素,或指向数组对象最后一个元素的元素(第 6.5.6 1173 节)
[注意:不要假设我对标准或 UB 了解很多,我只是碰巧发现了这个]
现在另一方面
因此我的问题是:从实验来看,似乎在某些体系结构(例如 x86-64)上,两个数组之间的指针差异提供了合理的、可重现的结果。它似乎与这些架构的硬件相当吻合。那么某些实现是否真的确保了特定的行为?
例如,在野外是否有一个实现可以保证a并且b存在char*,我们有a + (reinterpret_cast<std::ptrdiff_t>(b)-reinterpret_cast<std::ptrdiff_t>(a)) == b?