如果一个数组超出了另一个数组的末尾,则此代码将通过指针写入一个值。
#include <stdio.h>
#include <inttypes.h>
extern int first[], second[];
#define ADDR_AFTER(ptr) ((uintptr_t)((ptr) + 1))
int test(int *an_int) {
*second = 1;
if (ADDR_AFTER(first) == (uintptr_t)an_int) {
// ubsan does not like this.
*an_int = 2;
}
return *second;
}
int first[1] = {0}, second[1] = {0};
int main() {
if (ADDR_AFTER(first) == (uintptr_t)second) {
printf("test: %d\n", test(second));
printf("x: %d y: %d\n", *first, *second);
}
}
Run Code Online (Sandbox Code Playgroud)
我绝不会直接比较两个指向不同对象的指针(因为我将它们转换为uintptr_t第一个)。我创建了一个指向数组末尾一位的指针(这是合法的),但我从未取消引用该指针。据我所知,这应该不打印任何内容,或者打印:
测试:2 x:0 y:2
当优化为或更低时,它会打印在 Clang 上-O1。-O2然而,在 处,它打印:
测试:1 …
我在这个站点上看到了很多链接列表的C实现示例,并且大多数将下一个指针放在每个节点的末尾,就像这样......
struct intNode1 {
int data;
intNode1 *next;
};
Run Code Online (Sandbox Code Playgroud)
为什么他们这样实现它们而不是像这样?
struct node {
struct node *next;
};
struct intNode2 {
struct node node;
int data;
};
Run Code Online (Sandbox Code Playgroud)
后一种实现链表的方法允许您的插入和删除代码在任何类型的节点上工作,并允许您创建通用列表类型,而前一种方式强制您从头开始实现每种类型的列表.
例如,这是使用两种节点的单链表的(不完整)实现:
struct intList {
struct intNode1 *head;
};
struct list {
struct node *head;
};
Run Code Online (Sandbox Code Playgroud)
现在,显然需要比较它的节点的泛型列表上的任何操作都需要一个指向比较函数的函数指针,但这通常可以隐藏在列表的不太通用的接口的实现中.例如:
/* Returns zero if successful or nonzero otherwise */
int list-insertInt(struct list *list, int n) {
struct intNode2 * newNode;
if(!(newNode = malloc(sizeof *newNode)) {
return -1;
}
newNode->data = n;
return list-insertNode(list, (struct node *)newNode);
} …Run Code Online (Sandbox Code Playgroud) 我正试图在我的Leopard MacBook Pro上用x64汇编构建Hello World.它汇总很好,但是当我尝试链接它时我得到了这个错误:ld:symbol dyld_stub_binding_helper未定义(通常在crt1.o/dylib1.o/bundle1.o中)用于推断架构x86_64
我用ld -o hello64 hello64.o -lc加载它
我的装配工是Yasm.
编辑:据我所知,与32位代码不同,你必须自己提供存根助手,因为我不知道64位存根助手是如何工作的,我会像Bastien所说的那样做并拥有GCC链接它,因为它包含它自己的存根助手.
卫生署!劳工处会自动包含crt1.o如果我的程序集的入口点已经_main代替_start.