LINUX.ORG.RU

Какая-то дичь в Си

 , ,


0

1
#include <stdio.h>
void log(int x)
{
  int *ptr = x;
  *ptr += 17;
  printf("%d\n", *ptr);
}

int main(void)
{
  int n = 20;
  log(&n);
  return 0;
}


Этот код падает с сегфолтом
Почему нельзя так делать? Или может я неправильно делаю?

★★

Последнее исправление: beastie (всего исправлений: 2)
void log(int *x)
anonymous
()

Я бы сказал, что он компилироваться не должен, а не то что сегфолтиться.

akk ★★★★★
()

Ты неправильно делаешь, нельзя приводить указатель к целому, и компилятор тебе об этом, вообще-то, сказал. Не пиши сюда, пожалуйста, пока твой код не соберётся с -Wall -Wextra -Werror

slovazap ★★★★★
()
sizeof(int *)
anonymous
()
#include <stdio.h>
void log(unsigned long long x)
{
  int *ptr = x;
  *ptr += 17;
  printf("%d\n", *ptr);
}

int main(void)
{
  int n = 20;
  log(&n);
  return 0;
}
anonymous
()
#include <stdio.h>

int main() {
	printf("%d %d\n", sizeof(int), sizeof(int*));

	return 0;
};

./test

4 8

sevenredlines
()

Если уж так хочется извращений, то лучше сделать так:

- void log(int x)
+ void log(uintptr_t x)

Потому что у тебя в x адрес переменной не влезет (потому что она знаковая).

joy4eg ★★★★★
()

Почему нельзя так делать?

А у тебя при передаче параметра &n не округляется с uint64_t до uint32_t ?
P. S. У меня не валится с сегфолтом, всё ок.
Особенно, если сделать так:

#include <stdio.h>
#include <stdint.h>
void _log(uint32_t x)
{
  int *ptr = (int *)x;
  *ptr += 17;
  printf("%d\n", *ptr);
}

int main(void)
{
  int n = 20;
  _log((uint32_t)&n);
  return 0;
}
@D:\PROGS\CodeBlocks\MinGW\bin\gcc.exe -Wall -std=c99 -o d.exe d.c
@D:\PROGS\CodeBlocks\MinGW\bin\strip.exe d.exe

pacify ★★★★★
()

Учи матчасть!

Ты берешь указатель от n, пихаешь его в бедный int, потом берешь преобразуешь обратно в указатель, сдвигаешь его на 14 * sizeof(int) байт и пытаешься разыменовать.

Что. Тут. Может. Пойти. Так?

a1batross ★★★★★
()

а вот на 32 битной системе этот код работает

неправильно ты делаешь то, что преобразуешь указатель (который на 64 битной системе 64 битный) в int, который 32 бита, в результате адрес обрезается, и разыменование *ptr += 17; происходит уже с неправильным адресом, что вызвает сегфолт

Harald ★★★★★
()
Ответ на: комментарий от joy4eg

Мне хочется сделать так:
1. определяется, число это или указатель
2. модфикация
3. вывод
Или в Си так нельзя?

mystery ★★
() автор топика
Ответ на: комментарий от mystery

определяется, число это или указатель

Указатель это тоже число. И ты должен явно указать, что ты используешь (int или *int).

Или в Си так нельзя?

Иди лучше PHP изучай ...

joy4eg ★★★★★
()
Ответ на: комментарий от mystery

определяется, число это или указатель

Твоя программа не может анализировать свой код, чтобы взять мета-инфу. Она [мета-информация] доступна только компилятору. Все указатели для твоей программы (для полученного машинного кода) - это обычные числа. Их [переменные] твой машинный код на этапе не выполнения не отличит от float/int.

pacify ★★★★★
()
Последнее исправление: pacify (всего исправлений: 2)
Ответ на: комментарий от mystery

определяется, число это или указатель

то что хранится в указателе как-бы тоже число, непонятно чего ты хочешь от бедного компутера

mbivanyuk ★★★★★
()

МАЙ ГАДБЛ ПРОЧИТАЙ УЖЕ ПЕРВЫЕ ГЛАВЫ КНР СЦУК

anonymous
()

void log(int x)
log(&n)

Ты передаешь указатель вместо целого, неужели ты сам не понимаешь что это не сработает? Да и размер то разный у них.

mbivanyuk ★★★★★
()
Последнее исправление: mbivanyuk (всего исправлений: 1)
#include <stdio.h>
void log(int *x)
{
  int *ptr = x;
  *ptr += 17;
  printf("%d\n", *ptr);
}

int main(void)
{
  int n = 20;
  log(&n);
  return 0;
}

Это должно быть так.

Deleted
()
Последнее исправление: romeo250501 (всего исправлений: 2)

не делай так и так не делай:


#!/usr/bin/tcc -run 
#include <stdio.h>

void 
log(int x){
        int *ptr = &x;
        *ptr += 17;
        printf("%d\n", *ptr);
}

int
main(void){
        log(20);
        return 0;
}
qulinxao ★★☆
()
Ответ на: комментарий от mystery

можно - например созданием таблицей в твоей функции всех мест откуда у тя вызывается твоя функция что бы твоя_функция могла «по звёздам» определить ей передали число или указатель на число

----------------------

не надо так делать кстати.

qulinxao ★★☆
()
Ответ на: комментарий от anonymous

Почему не работает прямая аналогия с электронной лампой? (там решётка, а у транзистора аналогичного нет)

pacify ★★★★★
()

Передаём указатель
void log(int x)
DOING IT WRONG

mittorn ★★★★★
()

А что столько тупорылых вопросов по C образовалось последнее время? Вчерашние школьники к поступлению в универы готовятся?

CatsCantFly
()
Ответ на: комментарий от UVV

Нельзя. Можно только к intptr_t и только в очень специфичных случаях. ТС это точно не нужно, поэтому просто «нельзя».

slovazap ★★★★★
()
Ответ на: комментарий от UVV

Можно

А ещё можно числа с плавающей точкой на равенство проверять. И многобайтные константы делать ('abc'). И логику вперёд-назад на goto делать.

i-rinat ★★★★★
()
Ответ на: комментарий от UVV

Ах, всё-таки «не надо» вам знакомо, подумать только. И примеры у вас замечательные, ещё бы AVRный код привели.

slovazap ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.