C++中的结构是否按顺序分配内存?每次都以某种方式获得指针比较的正确答案

Are Structs in C++ allocated memory sequentially? Somehow getting correct answer for pointer comparison everytime

本文关键字:方式获 比较 答案 指针 是否 结构 顺序 分配 内存 C++      更新时间:2023-10-16

我正在尝试解决一个问题。

问题定义:给定一个包含 n 个节点的单链表。修改前半节点的值,使第一个节点的新值等于最后一个节点的值减去第一个节点的当前值,第二个节点的新值等于倒数第二个节点的值减去第二个节点的当前值,前半部分节点也是如此。如果 n 为奇数,则中间节点的值保持不变。请注意,链表的半节点保持不变。

EG : 6 3 5 4 10

答: -4 -1 5 4 10

我编写了一个程序来跟踪下半部分的节点,其顺序与使用递归处理所需的顺序相反。但是,出于粗心大意,我比较了两个指针,以检查两个指针是否相互交叉以停止处理它们。

我每次都正确获得输出。

完整代码

#include <bits/stdc++.h>
using namespace std;
struct Node
{
int data;
struct Node* next;
};
struct Node* modifyTheList(struct Node *head);
void push(struct Node **head_ref, int new_data)
{
struct Node* new_node =(struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = *head_ref;    
*head_ref = new_node;
}
void printList(struct Node *head)
{
if (!head)
return;
while (head->next != NULL)
{
cout << head->data << " ";
head = head->next;
}
cout << head->data << endl;
}
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
struct Node *head = NULL;
while(n--){
int a;
cin>>a;
push(&head, a);
}
head = modifyTheList(head);
printList(head);
}
return 0;
}
void modify(Node *head ,Node** left)
{
if(head!=NULL)
{
modify(head->next,left);
if(head >= *left )            //line of concern, comparing pointers
return;
else
{
(*left)->data=(*left)->data-head->data;
(*left)=(*left)->next;
}
}
}
struct Node* modifyTheList(struct Node *head)
{
if(head==NULL || head->next==NULL )
return head;
struct Node *temp = head;
modify(head,&temp);
return head;
}
  1. 有人可以告诉我这样比较有效吗?

  2. 如果这不成立,它是如何通过在线评委的测试用例的?

有人可以告诉我这样比较有效吗?

不能直接比较指针,除非它们指向同一数组的子对象或同一对象的成员。从形式上讲,不属于同一数组的对象被视为单独的1 元素数组的一部分。比较它们的指针没有定义的结果。引用 N4296:

§5.9 关系运算符 [expr.rel] ְְ¶3

比较对象86的指针定义如下:
(3.1( — 如果两个指针指向同一数组的不同元素,或者 其子对象,指向具有较高元素的指针 下标比较更大。
(3.2( — 如果一个指针指向 元素,或其子对象,以及另一个指针 将一个指向数组的最后一个元素,即后一个指针 比较更大。
(3.3( — 如果两个指针指向不同的 同一对象的非静态数据成员,或此类对象的子对象 成员,递归地指向后来声明的成员的指针 如果两个成员具有相同的访问控制,则比较更大 (第11条(,前提是他们的班级不是工会。


86(为此目的,不是数组元素的对象被视为属于单元素数组;参见5.3.1。

所以你不能直接比较,你的程序正式具有未定义的行为。但是,这种比较可能很有用,这就是为什么该标准为您提供了另一种方法:

§20.9.6 比较 [比较] ְְ¶14

对于更大、更少、greater_equal和less_equal的模板,任何指针类型的专用化 生成总订单,即使内置运算符 <、>、<=、>= 不生成

因此,只需将head >= *left替换为调用std::greater_equal<Node*>(head, *left)即可很好地定义您的代码。


如果这不成立,它是如何通过在线评委的测试用例的?

未定义的行为意味着语言规范允许任何结果。"工作"是一种可能的结果。你不能指望它总是结果。

不,绝对不能保证不同分配的内存的关系位置。

如果这不成立,它是如何通过在线评委的测试用例的?

(来自我(的简单答案是说你(不(幸运。事实是,内存分配/映射的机制很复杂,涵盖了更多的层:应用程序(malloc(,C库实现,操作系统和硬件。连续的malloc请求可能会返回一些连续的内存,在某些情况下甚至有可能。这绝不是保证,很容易中断(例如,在一系列交织在一起的mallocfree之后(。

此外,如@StoryTeller所示,将指针(相等性除外(与不同对象进行比较是 UB。