考虑到 C++17 中引入的语义变化(例如在具有正确地址和类型的指针自 C++17 以来是否仍然始终是有效指针中进行了讨论) ,XOR 链接列表以一种对我来说看起来很可疑的方式使用指针算术。)。它们现在会导致未定义的行为吗?如果是这样,可以通过洗涤来拯救它们吗?
编辑:
维基百科文章仅包含有关指针和整数之间转换的简短注释。我默认(现在明确声明)指针首先被转换为足够大小的整数类型以适合它们,然后对整数进行异或。因此,操作理论中列出的 XOR 属性保证只有从指针获得一次的整数才会被转换回它们。根据标准,从指针到整数的实际映射可以是任意注入。除此之外我不依赖任何假设。
标准是否允许使用它们并访问仍然存在的对象?C++17 之前?从 C++17 开始?
就拿int ptr={10,20,30,40,50}
我明白
print("%d", *ptr++);
Run Code Online (Sandbox Code Playgroud)
在这样的陈述中,对运营商的评估是从右到左.因此,在*ptr++ 该++会获得第一,然后进行评估ptr,然后*
所以要确认同我写了一个程序
#include<stdio.h>
int main()
{
int array[] = { 10, 20, 30, 40, 50 };
int *q1 = array;
printf("q1 = %p\n",q1);
printf("*q1++ = %d\n",*q1++);
printf("q1 = %p\n",q1);
printf("*q1++ = %d\n",*q1);
}
Run Code Online (Sandbox Code Playgroud)
上述程序的输出与上述逻辑的预期运算符优先级不同.我得到的输出是
q1 = 0x7ffffcff02e0
*q1++ = 10
q1 = 0x7ffffcff02e4
*q1++ = 20
Run Code Online (Sandbox Code Playgroud)
但我在期待
q1 = 0x7ffffcff02e0
*q1++ = 20
q1 = 0x7ffffcff02e4
*q1++ = 20
Run Code Online (Sandbox Code Playgroud)
那么运营商的优先权是不是从右到左发生的?或者我的理解有些不对劲?
UPDATE
现在就是这个东西.即使我把这些括号放在所说的*(ptr ++)执行输出没有改变这里是新的代码
#include<stdio.h>
int main()
{ …Run Code Online (Sandbox Code Playgroud) 我只是在处理数组时尝试使用指针,而且我对C++处理数组的方式感到有些困惑.以下是我写的相关代码:
//declare a string (as a pointer)
char* szString = "Randy";
cout << "Display string using a pointer: ";
char* pszString = szString;
while (*pszString)
cout << *pszString++;
Run Code Online (Sandbox Code Playgroud)
首先,当我尝试使用cout来编写"pszString"中的内容时(没有取消引用)我有点惊讶地看到它给了我字符串.我只是假设它是因为我给指针一个字符串而不是一个变量.
真正吸引我注意的是,当我从行中删除星号时,cout << *pszString++;它打印出"Randyandyndydyy".我不确定为什么它会写入数组然后再用1个字母再写一次.我的理由是,在写入字符串后,增量运算符会立即将索引带到下一个字母,然后才能到达空终止符.我不明白为什么null终止符不会导致循环在第一次输出字符串后返回false,否则.这是正确的推理吗?有人可以解释我是否在数组和指针之间得到这种关系?
我试图通过指针算法迭代结构数组.然而它给了我无法理解的结果.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int hours;
int minutes;
int seconds;
} Time;
void time_print(Time t)
{
printf("Time is: %d:%d:%d\n", t.hours, t.minutes, t.seconds);
}
int main(void)
{
Time *testTimePointers[2];
testTimePointers[0] = malloc(sizeof(Time));
testTimePointers[0]->hours = 11;
testTimePointers[0]->minutes = 10;
testTimePointers[0]->seconds = 9;
testTimePointers[1] = malloc(sizeof(Time));
testTimePointers[1]->hours = 7;
testTimePointers[1]->minutes = 6;
testTimePointers[1]->seconds = 5;
time_print(*(testTimePointers[0]));
time_print(*(testTimePointers[1]));
printf("=============\n");
Time *ttp_cur = NULL;
ttp_cur = testTimePointers[0];
time_print(*(ttp_cur));
ttp_cur++;
time_print(*(ttp_cur));
free(testTimePointers[0]);
free(testTimePointers[1]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果是
Time is: 11:10:9
Time is: …Run Code Online (Sandbox Code Playgroud) 考虑以下程序:(参见此处的现场演示)
#include <stdio.h>
int main(void)
{
char c[]={'s','h','r','e','y','a','\0'};
char *ptr=c;
for(int i=0;i<6;i++)
printf("%c",ptr[i]);
printf("\n");
char (*s)[7];
s=&c;
for(int i=0;i<6;i++)
printf("%c",(*s)[i]);
printf("\n");
ptr=&c[5]; // ptr points to 6th char of string
for(int i=5;i>=0;i--)
printf("%c",ptr[i]);
}
Run Code Online (Sandbox Code Playgroud)
该计划没有给出预期的结果.我得到的结果是:
SHREYA
SHREYA
一个
但如果我写下最后一个循环如下,它工作正常.
for(int i=5;i>=0;i--)
printf("%c",c[i]);
Run Code Online (Sandbox Code Playgroud)
关于指针我在这里理解错了什么?为什么我printf("%c",ptr[i]);在last for循环中写入时只有最后一个char作为输出.
看下面的代码:
#include <stdio.h>
int main()
{
char str[80];
int n;
scanf("%s%n",str,&n);
printf("%s\t%d",str,n);
putchar('\n');
getchar(); //to remove '\n'
scanf("%s%n",&str,&n);
printf("%s\t%d",str,n);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是输入和输出:
abc
abc 3
123
123 3
Run Code Online (Sandbox Code Playgroud)
我们知道,它scanf是一个可变参数函数,因此在调用它时它的参数不会被转换.因此,参数必须以与它们应该完全相同的类型传递.然而,类型strIS char *(从衰减char (*)[80]),而&str具有的类型char (*)[80],虽然它们具有相同的值,即&str[0].
那么为什么可以scanf("%s",&str);正常工作而不会因指针运算而导致段错误呢?
我试图让我的脚进入C,并编写了这个程序,在随机位置显示我的RAM的kb.这是代码,它工作正常:
#include <stdio.h>
int main(){
char *mem;
for(int i =0; i < 1024; i++){
mem++;
printf("%c", *mem);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
之后,我在代码中进行了以下更改,每次运行程序时都会出现段错误:
#include <stdio.h>
// Just added this signature
int main(int argc, char *argv[]){
char *mem;
for(int i =0; i < 1024; i++){
mem++;
printf("%c", *mem);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的蜘蛛感官告诉我,我得到的段错是随机的,也应该在第一个例子中引起,但是一次又一次地运行不同的程序使它看起来像可预测的行为.
$ gcc -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Run Code Online (Sandbox Code Playgroud) 我应该创建一个变量
long long hex = 0x1a1b2a2b3a3b4a4bULL;
Run Code Online (Sandbox Code Playgroud)
然后定义指向1a1b,2a2b,3a3b和4a4b的4个指针.然后我打印那些双字节的地址和值.
我的方法是创建一个指针
long long *ptr1 = &hex;
Run Code Online (Sandbox Code Playgroud)
然后使用指针算法来获取下一个值.我意识到增加这个指针会增加长字节,而不是像我需要的那样增加2个字节.创建一个短指针
short *ptr1 = &hex;
Run Code Online (Sandbox Code Playgroud)
是我需要的,但我的编译器不会让我,因为数据类型不兼容.我该如何解决这个问题?有没有办法创建一个递增2个字节的指针并将其分配给更大数据类型的变量?
对于以下代码:
#include <stdio.h>
int main()
{
int a[][3] = {1, 2, 3, 4, 5, 6};
int (*ptr)[3] = a;
printf("%d %d ", (*ptr)[1], (*ptr)[2]);
++ptr;
printf("%d %d\n", (*ptr)[1], (*ptr)[2]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
应该打印什么?我期待:
2 3 3 4
但输出是:
2 3 5 6
我期待输出,2 3 3 4
因为最初ptr它指向二维数组的第一行a[][3].因此(*ptr)[1],首先printf会给我们2,就像明智的(*ptr)[2]会给我们3.但是++ptr在线之后它将开始指向第一行的第二个元素a[][3].因此(*ptr)[1],第二行现在应该给我们3,同样(*ptr)[2]应该给我们4.
我注意到Clang的这个警告:
warning: performing pointer arithmetic on a null pointer
has undefined behavior [-Wnull-pointer-arithmetic]
Run Code Online (Sandbox Code Playgroud)
详细信息,正是此代码触发此警告:
uint8_t *end = ((uint8_t*)0) + sizeof(uint8_t) * count;
Run Code Online (Sandbox Code Playgroud)
为什么在从不同于零的整数获得的非空指针上执行相同操作时禁止对空指针进行算术运算不会触发任何警告?
更重要的是,C标准是否明确禁止空指针算法?