- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
int main(void)
{
char a[8], b[8];
char *a_ptr = a+8;
char *b_ptr = b;
printf("a_ptr = %p, b_ptr = %p\n", a_ptr, b_ptr);
if (a_ptr != b_ptr)
{
printf("a_ptr != b_ptr\n");
}
else
{
printf("a_ptr == b_ptr\n");
}
if ((uintptr_t)a_ptr != (uintptr_t)b_ptr)
{
printf("(uintptr_t)a_ptr != (uintptr_t)b_ptr\n");
}
else
{
printf("(uintptr_t)a_ptr == (uintptr_t)b_ptr\n");
}
return EXIT_SUCCESS;
}
bootcamp_dropout 02.02.2019 01:18 # +1
j123123 02.02.2019 02:12 # +5
> Two pointers compare equal if and only if both are null pointers, both are pointers to the same object(including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space. .111)
> 111)Two objects may be adjacent in memory because they are adjacent elements of a larger array or adjacent members of a structure with no padding between them, or because the implementation chose to place them so, even though they are unrelated. If prior invalid pointer operations (such as accesses outside array bounds) produced undefined behavior, subsequent comparisons also produce undefined behavior.
bootcamp_dropout 02.02.2019 02:35 # +1
1)gcc и clang печатают разные адреса и, соответственно, сообщение о том что не равны и так, и эдак справедливо.
2)vc проработав секунд 10, не печатает ничего.
Более того, согласно приведенному тобой стандарту, "or because the implementation chose to place them so, even though they are unrelated"
Каким компилятором ты пользовался?
j123123 02.02.2019 02:55 # 0
j123123 02.02.2019 03:02 # 0
bootcamp_dropout 02.02.2019 03:25 # +3
в
Потому что он видит что у указателей разное "происхождение", и ему становится похуй.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61502#c30
Rooster 02.02.2019 11:42 # +2
Вот в S" Forth" все оптимизации делает программист, именно поэтому я за S" Forth". вот эт было бы другое дело.
bootcamp_dropout 02.02.2019 15:58 # +1
PA3yMHblu_nemyx 02.02.2019 16:22 # 0
Вот так, например, можно:
bormand 03.02.2019 08:04 # +1
Rooster 03.02.2019 08:23 # 0
Введите название языка: Forth >ok
bormand 03.02.2019 08:30 # 0
Rooster 03.02.2019 08:58 # 0
о да, это один из главных минусов. Потому и пишут стековые диаграммы, я даже в сложных случаях на каждой строчке их пишу. Можно облегчить страдания если стараться писать маленькие определения, ещё облегчают дело LOCALS|
bormand 03.02.2019 09:33 # 0
PA3yMHblu_nemyx 03.02.2019 14:37 # 0
А адреса глобальных переменных могут быть constexpr? Допустим, что программа может загружаться по произвольному адресу, но при этом смещения глобальных объектов относительно начала образа фиксированы.
j123123 02.02.2019 17:13 # +3
PA3yMHblu_nemyx 02.02.2019 17:21 # +2
Кстати, нашёл не очень старое говно:
http://govnokod.ru/24539
Забавно, что 25349 получается из 24359 перестановкой цифр.
Rooster 02.02.2019 21:04 # 0
PA3yMHblu_nemyx 02.02.2019 21:20 # 0
Для пирфоманса компиляторы выравнивают данные, между переменными появляются неиспользуемые промежутки. Способ выравнивания может зависеть от флагов оптимизации.
2. Я чуть выше написал про предварительное выделение памяти в стеке и про push. Предварительное выделение и push приводят к размещению локальных переменных в противоположных порядках.
3. Часть локальных переменных компилятор может утоптать в регистры, чтобы не тратить память.
*****
Да, компилятор знает, как он это будет делать. Но у «gcc», вероятно, проблема из-за его кроссплатформенности. Нужно поддерживать кучу рахит-тинктур. Парсер, оптимизатор, кодогенератор разделены. Чтобы они могли сообщать друг другу дополнительную информацию, нужны хаки.
PA3yMHblu_nemyx 02.02.2019 21:40 # 0
Зачем смешивать способы выделения?
В «Паскале» выделять переменные можно только в самом начале функции. Там всё просто: сразу выделил место в стеке и разместил подряд в прямом порядке.
В «C99» и в «C++» переменные можно выделять в операторе «for» и в некоторых других. Они могут занимать место в стеке временно, ведь они вне блока не используются (использовать их вне блока –— UB), поэтому их можно пушить. И вот это приводит к перемешиванию адресов.
Итого: взятие адреса локальной переменной –— это довольно небезопасная операция, выносящая мозг оптимизатору.
cmepmop 03.02.2019 00:30 # 0
Rooster 03.02.2019 08:15 # 0
bormand 02.02.2019 07:53 # 0
PA3yMHblu_nemyx 02.02.2019 16:04 # 0
С глобальными переменными проще: они как правило размещаются в прямом порядке и в регистрах не хранятся. Но даже тут можно нарваться на паддинги: кококомпилятор может выравнивать переменные по-разному, в зависимости от параметров оптимизации.
j123123 02.02.2019 04:56 # +5
GCC has a somewhat aggressive interpretation on the standard, so it compiles p == q to false if it determines that they are derived from different objects (see GCC bug 61502 for details). This has the fun effect that it is possible to get pointers p and q that point at the same memory address, but p == q evaluates to false, as in
that prints
0x7f7fffffdafc 0x7f7fffffdafc 0
on my development machine when compiled with a recent GCC.
PA3yMHblu_nemyx 02.02.2019 12:43 # 0
PA3yMHblu_nemyx 02.02.2019 14:04 # 0
При разных значениях параметра оптимизации они могут разместить x и y на разном расстоянии друг от друга, но всегда возвращают правильный результат (p == q, если нет дыр, и p != q, если есть дыры). «GCC» же всегда возвращает p != q вне зависимости от того, как реально размещены x и y.
PA3yMHblu_nemyx 02.02.2019 14:11 # +2
gcc без оптимизации: Что ж, всё верно: p≠q, p>q.
gcc -O2: Получилось, что p не больше q, p не меньше q, но p и не равно q. Как будто сравнили два NaN.
PA3yMHblu_nemyx 02.02.2019 14:16 # +4
Итог (gcc -O2):
Итак, p <= q; p >= q; p - q == 0, но при этом p != q.
PA3yMHblu_nemyx 02.02.2019 14:19 # 0
gost 02.02.2019 15:20 # 0
PA3yMHblu_nemyx 02.02.2019 15:28 # 0
PA3yMHblu_nemyx 02.02.2019 15:42 # −1
Правда, пока не знаю, в каком коде это можно применить.
PA3yMHblu_nemyx 02.02.2019 16:30 # +1
bormand 02.02.2019 16:36 # 0
PA3yMHblu_nemyx 02.02.2019 14:26 # 0
cmepmop 02.02.2019 16:05 # 0
Rooster 02.02.2019 21:08 # 0
guest8 03.02.2019 13:25 # −999