LINUX.ORG.RU

разве это правильно

 


0

1

Всем привет. Сегодня увидел в коде программы

char CompressStr(char s[256])
... 
some code
...
и офигел... прогу писал математик. Блин,зачем же так передавать параметры в функцию. неужто он не знает указателей? (я объяснял что это переменная, содержащая адрес другой переменной, а еще бывает указатель на указатель, тут его реально «замкнуло...») кто-нибудь может скомпилить это код (с флагами -О0 если можно) и выложить ассемблерные инструкции сюда, интересно посмотреть.

Ни линукса, ни компилятора под рукой нет, а посмотреть интересно. )))

А что реально, так можно писать на Си? Или это плюсовики так могут?


Что не так? s в данном случае — указатель.

theNamelessOne ★★★★★
()

Это и так указатель. В С нельзя передать содержимое массива вот так. Хотя можно запихнуть такой массив в структуру и передать аргументом её.

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

Хотя можно запихнуть такой массив в структуру и передать аргументом её.

Только массив в структуре тоже будет указателем.

theNamelessOne ★★★★★
()

А

CompressStr("some useless line of text")

вообще сломает тебе мозг?

buddhist ★★★★★
()

Видел на одной странице.

anonymous
()

Из KnR:

значение переменной или выражения типа «массив» является адресом нулевого элемента массива

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

Блин, я чай пролил на уголок KnR... *набор трудноразличимых ругательств*

zekka
()

А что реально, так можно писать на Си?

Можно, здесь всё корректно.

yoghurt ★★★★★
()
void main(int argc, char** argv)

эквипенисуально

void main(int argc, char* argv[])
http://c-faq.com/ansi/maindecl.html

ну и про указатели/массивы как параметры http://c-faq.com/aryptr/aryptrparam.html...

Since arrays decay immediately into pointers, an array is never actually passed to a function. You can pretend that a function receives an array as a parameter, and illustrate it by declaring the corresponding parameter as an array:

void f(char a[]) { ... }

Interpreted literally, this declaration would have no use, so the compiler turns around and pretends that you'd written a pointer declaration, since that's what the function will in fact receive:

void f(char *a) { ... }

Тоже монофаллично :)

slackwarrior ★★★★★
()
Последнее исправление: slackwarrior (всего исправлений: 1)

RTFM про «array decay».

anonymous
()

Хм... ну ладно. просто подумалось, что код

char CompessStr(char s[256])
неэквивалентен коду
char CompessStr(char *s)
на уровне ассемблерных инструкций и команд. Или компилятор все сам соптимизирует.

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

Ведь не будет же из стек-пойнтера вычитаться 256?

А почему это собственно должно происходить, как ты считаешь? Это что, локальная переменная?

shamaz
()
Ответ на: комментарий от Dennis7

Он и с точки зрения Си неэквивалентен, в общем-то.

yoghurt ★★★★★
()

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

ErasimHolmogorin
()

разве это правильно

Да, это корректная конструкция. А что такого? Зато понятно, что массив должен быть длиной именно 256 элементов (да, я сам тоже так пишу иногда).

tailgunner ★★★★★
()

Это эквивалентно записи

char s[256];
char foo(s);

Так что математик дело своё разумеет

chg ★★★★★
()

Сегодня день математиков-программистов на ЛОРе?

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

В чем разница? Передаётся в любом случае указатель. А вот где массив будет жить зависит от контекста. Если внутри функции, то лучше static

chg ★★★★★
()
#!/bin/bash

function gen()
{
  echo "#include <stdio.h>"
  echo "char fun($1) {"
  echo "  printf(\"%s\", s);"
  echo "  return ((char*)s)[2];"
  echo "}"
  echo "int main() {"
  echo "  char text1[256] = \"text1\";"
  echo "  char text2[] = \"text2\";"
  echo "  char* text3 = \"text3\";"
  echo "  printf(\"%c\\n\", fun(\"some code4\"));"
  echo "  printf(\"%c\\n\", fun(text1));"
  echo "  printf(\"%c\\n\", fun(text2));"
  echo "  printf(\"%c\\n\", fun(text3));"
  echo "  return 0;"
  echo "}"
}

index=0
for i in "char s[256]" \
         "char s[257]" \
         "char s[]" \
         "char* s" \
         "void* s"; do
  gen "$i" | gcc -O0 -S -xc - -o $index.s
  index=$((index+1))
done

md5sum *.s
$ ./run.sh
<stdin>: In function ‘fun’:
<stdin>:3:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘void *’ [-Wformat=]
502d7fd755683bfeee9bd2e1b6a4b550  0.s
502d7fd755683bfeee9bd2e1b6a4b550  1.s
502d7fd755683bfeee9bd2e1b6a4b550  2.s
502d7fd755683bfeee9bd2e1b6a4b550  3.s
502d7fd755683bfeee9bd2e1b6a4b550  4.s
anonymous
()

Блин,зачем же так передавать параметры в функцию. неужто он не знает указателей?

s и есть указатель. Перед тем, как учить других, почитай хотя бы k&r.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от anonymous

как пожелаешь

#!/bin/bash

index=0
for i in "char s[256]" \
         "char s[257]" \
         "char s[]" \
         "char* s" \
         "void* s"; do
  gcc -O0 -S -o $index.s -xc - <<EOF
#include <stdio.h>
char fun($i) {
  printf("%s", s);
  return ((char*)s)[2];
}
int main() {
  char text1[256] = "text1";
  char text2[] = "text2";
  char* text3 = "text3";
  printf("%c\n", fun("some code4"));
  printf("%c\n", fun(text1));
  printf("%c\n", fun(text2));
  printf("%c\n", fun(text3));
  return 0;
}
EOF
  index=$((index+1))
done

md5sum *.s

anonymous
()

Еще попробуй угадать что вернет sizeof(s) внутри функции.

vromanov ★★
()

Я что-то думал, что размер массива какую-нибудь пакость да внесет. ан нет:

cat 1.c 
#include <stdio.h>

void dosometh(char arr[12]){
	printf("arr: %s\n", arr);
}

int main(int argc, char** argv){
	int i;
	argv++; argc--;
	char a[12] = "0123456789";
	char b[20] = "some test msg";
	dosometh(a);
	dosometh(b);
	for(i = argc - 1; i > -1; i--)
		dosometh(*argv++);
}

gcc 1.c -o test

./test раз два три фигнякакаятодлинная
arr: 0123456789
arr: some test msg
arr: раз
arr: два
arr: три
arr: фигнякакаятодлинная

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от YLoS

Нет. У них, у математиков, просто другие приоритеты в кодировании. Отсутствуют, тыкскыть, основы кодерского ремесла. У них оно, ремесло, совсем другое.

Я смотрю на то, как кодит мой сын, и у меня волосы дыбом. Даром что он по результатам городской олимпиады по программированию идёт на «область». Собственно, его основные на данный момент увлечения - это математика и физика (на математике, для сравнения, на «городе» - полный балл, а на физике - 4-е, что-ли, место, с небольшим отрывом от максимума). А от программирования ему нужно, чтобы «вон та хреновина закрутилась», а уж как оно будет крутиться, ему совершенно не важно. Вопросы поддержки такого говнокода его тоже совершенно не интересуют. Поэтому он и не заморачивается.

Аналогичный подход встречал в работах других знакомцев, которые уже диссеры в Институте Математики писали. Но это вообще свойство [чрезмерной] специализации. У меня один дружок, будучи хардкорным физиком-оптиком, защищался по результатам работы в вирусологически-молекулярно-биологическом «Векторе». Как его эти самые биологи шпыняли за биологическую часть его работы: «и здесь все положенные „ку“ не сказаны, и там корявая формулировка итп». При том, что работа была, собственно, о применимости созданной другом и его коллегами установки в молекулярно-биологических исследованиях.

AlexM ★★★★★
()

Всё правильно. Число 256 компилятором будет проигнорировано, оно нужно в целях документации, для тех, кто станет вызывать функцию.

Deleted
()

s в данном случае тоже указатель. Просто память выделена на стеке. s - это указатель на эту стековую память. Передача через стек - вполне нормальный прием. Стек работает очень быстро. Иначе бы пришлось выделять память самому и заботиться об ее освобожднении. Это лишние накладные расходы и лишние хлопоты.

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