Я пытаюсь написать программу, имитирующую некоторый ассемблерный код (не спрашивайте меня, почему, лол), и она должна выглядеть примерно так.
Он должен использовать значение int, чтобы заполнить память структуры, состоящей из длинных значений.
Когда отлаживаю программу, в первой итерации sizeof(int)*a = 0
и все хорошо.
Но во второй итерации a=1
и sizeof(int)*1=4
, но &ss+sizeof(int)*a
равно не &ss+4
, а скорее &ss+0xA0
... Тогда для a = 2
, &ss+0x140
. Он постоянно умножается на 40 (десятичная система).
шестнадцатеричный 0xA0
= 4*40
десятичный. шестнадцатеричный 0x140
= 8*40
десятичный...
Как заставить это работать?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
long a[5];
} StructType1;
StructType1 foo()
{
StructType1 ss;
int bb = 7;
int a = 0;
while (a < 10)
{
memcpy(&ss + sizeof(int) * a, &bb, 4);
a++;
}
return ss;
}
int main()
{
StructType1 s = foo();
printf("%ld\n", s.a[0]);
}
Указатель всегда увеличивается с шагом, равным размеру типа данных, на который он указывает.
1. Я почти уверен, что long=8B(QWORD) и int=4B(DWORD), по крайней мере, по ссылке System V ABI. 2. Означает ли это, что когда я увеличу &ss на 1, оно увеличится на 1*sizeof(type_it_points_to)?
@LukaSavic, если вам нужен тип фиксированного размера, вы должны использовать тип фиксированного размера. Long, int и т. д. могут быть изменены.
@LukaSavic Да, когда вы увеличиваете &ss
на 1, адрес увеличивается на размер структуры.
@user3386109 user3386109 это имеет смысл, чувак. Никогда не думал об этом, sizeof(struct) равен 5*sizeof(long) и ровно 40B. Вот это да...
Возможно, вы могли бы указать указатель на char* и получить ожидаемый результат. (как это ни странно)
@Taekahn, не могли бы вы немного объяснить, как они могут быть изменены? в любом случае нельзя хранить больше 4 байт? Конечно зависит от архитектуры, но в данном случае
Похоже, вы проявили должную осмотрительность и убедились, что для вашей цели размер имеет смысл. Для тех, что следуют, C и C++ определяют только минимальный размер целочисленных типов и то, что они не могут быть больше, чем следующий тип. sizeof(int)
может быть от 2 до sizeof(long)
включительно. Некоторые люди, например Крей, в прошлом определяли их всех как одинаковые по размеру.
Вам действительно не нужно memcpy
. Следующее будет работать. long bb = 7 + (7 << 32); for (int i = 0; i < 5; i++) ss.a[i] = bb;
@user3386109 user3386109 спасибо за предложение, я уже пробовал это, и все было в порядке, но смысл упражнения заключался в том, чтобы преобразовать сборку в .c, и она явно работала с DWORD и помещала 10 DWORD из начального местоположения. Если посмотреть на мой ассемблерный код для кода .c выше, они очень похожи, поэтому я почти уверен, что почти достиг цели. Я почти уверен, что мне следует использовать int и memcpy, но я не вижу четкого способа сделать это. Если я использую char* и вызываю некоторую память, то у меня возникает проблема с возвратом char*, и я должен возвращать StructType1.
Если вы настаиваете, то использование char *
позволяет вам самостоятельно выполнять вычисления адресов: char *ptr = &ss;
и memcpy(ptr + sizeof(int) * a, &bb, sizeof(int));
@ user3386109 большое спасибо!! мне должно было прийти в голову сделать это таким образом .. спасибо за помощь, узнал несколько вещей в этом обсуждении :)
Примечание: любой объект можно смело рассматривать как массив символов, что и происходит с char *ptr = &ss;
, но обратное неверно. Вы не можете быть уверены, что StructType1 * ssp = (StructType1 *)a_char_array;
правильно выровнена в памяти или что-то еще и не взорвется вам в лицо.
Как прокомментировал пользователь3386109, тип &ss
— указатель на объект StructType1
, поэтому добавление к нему целого числа n
вычисляет адрес n
-го следующего объекта в массиве таких объектов, умножая n
на размер объекта, чтобы получить адрес в байтах .
Для вашей цели вы должны указать &ss
как указатель на тип символа.
Вот модифицированная версия:
#include <stdio.h>
#include <string.h>
typedef struct {
long a[5];
} StructType1;
StructType1 foo(void) {
StructType1 ss;
int bb = 7;
int a = 0;
int n = sizeof ss / sizeof(int);
while (a < n) {
memcpy((char *)&ss + sizeof(int) * a, &bb, sizeof(int));
a++;
}
return ss;
}
int main() {
StructType1 s = foo();
for (int i = 0; i < 5; i++) {
printf("%ld%c", s.a[i], " \n"[i]);
}
return 0;
}
Что, если
int
не вдвое меньшеlong
?