LINUX.ORG.RU

Несколько вопросов новичка по Си

 , ,


0

3
  1. Как работает указатель?
  2. Функция sub получает делимое и вычитает из него делитель Она ничего не возвращает и просто меняет значение переменой по указателю. Но когда вызываю функцию, приходится указывать & и имя переменной. Нельзя ли просто передать переменную и почему?
    void sub(int* f, int g)
    {
      *f = *f - g;
    }
    
    int main(void)
    {
      int number = 15, div = 7;
      sub(&number, div);
      printf("%d\n", number);
      return 0;
    }
  3. Насколько этот код говно? Что стоило бы исправить? Спасибо!
★★
Ответ на: комментарий от anonymous

Садись, неуч, два!

Ты реально думаешь, что твоя потуга чего-то стоит?

If the return type of the main function is a type compatible with int, a return from the
initial call to the main function is equivalent to calling the exit function with the value
returned by the main function as its argument;11) reaching the } that terminates the
main function returns a value of 0.
AnonCxx
()
Ответ на: комментарий от anonymous

exit

И gcc сматюкается, что в функции, которая должна int вернуть, нет return'а.

Да и вообще, exit — функция из stdlib, ее используют только при необходимости аварийного выхода (например, в обработчике сигналов или при проверке условий).

Ты всерьёз думаешь, что ему интересно?

Думаю, это вообще к нему отношения не имеет.

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

Это разные вещи. char* — указатель, т.е. для того, чтобы прочитать строку, его надо разыменовать сначала и выяснить адрес, где хранится эта строка.

О боже - что ты несёшь. В результате разименования получится char, а не строка.

char[] — уже адрес, его разыменовывать не нужно.

Действительно, а char * не адрес. Ну бывает, бывает. Для получения char char[] нужно точно так же разименовывать.

Для ТСа: в случае char* компилятор отводит под переменную дополнительные 4-8 байт

Познания в районе помойки. В случае с char * - это будет копия кого-нибудь глобала, который точно так же свернётся к оригиналу.

в случае char[] это место не отводится, и в функции вроде sprintf(str, ...) фактически на место str сразу подставляется адрес — константа..

Нет, у тебя будет инициализоваться в стеке строка перед вызовом sprintf(str, ...).

В случае же с char * - у тебя будет строка не на стеке, а в глобале к которой можно без копирования на стек обращаться.

ТСу: ты можешь сразу выделить указатель через malloc:

Действительно, выделить указатель маллоком.

int * ptr = (int[]){0};

Как там в 80-х?

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

Ламерки уже кооперируются против меня - мило. Увидел победку и решил подмазаться - огорчу тебя, победка тебе лишь показалась. Такое бывает. Ничего.

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

Слив засчитан. Как там, нравиться кукарекать нихрена не зная? Ну вот кукарекай, только тогда, когда меня нет и не со мною. Противопоставлять свои «познания» против меня - глупо и завершается всегда тем, чем завершилось и сейчас.

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

char[] не фигурирует как тип аргумента функций

оно там синтаксически фигурирует если чё - ибо С изначально носимый ассемблер - и да покури дисер Ричи Дениса про субрекурсивность.

зы.

ты прав в той системе аксиом которые в данной дискуссии продвигаеш

.

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

какая-такая память выделяется для char[] при определении внутри структуры

если просто [] то это синтаксически *

если [const] то это синтаксически резервирование места в пространстве смещений

про union - пока их не добавили в язык явно - обходились наложением полей - от того то и пространство имён полей записей в Си не вложенно в структуру а общее у всех структур -

крч Си не Паскаль(наше вам почтение) - забавно как «ТЫ» защищая Си испозуешь о Си представление как о языке Вирт-школы с чёткой проработаностью «концепций» = когда как «на самом деле» Си это носимый ассемблер языковой лаборатори в которой Юникс первичен - а си не имел годного рекурсивного чёткого определения первые ~20 лет своей юности(включая перинатальный период)(см Гайя Стила кста и желательно первое издание начала 80ых если сможешь найти)

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

оно там синтаксически фигурирует если чё

Да, но реально нет. Поэтому именно как тип аргумента он не фигурирует.

ибо С изначально носимый ассемблер

Тот ассемблер уже давно протух, да и си стал другим. Толку о нём рассуждать.

и да покури дисер Ричи Дениса про субрекурсивность.

Мне лень курить что-то протухшее. Идеи я понимаю итак, а всё остальное мне не интересно, ибо сейчас это не котируется. Язык является очень слабым набором кастылей вызванных ограничениями той эпохи и возможно ограничениями в понимании того же ричи.

Хотя на самом деле тогда он был мощнее из-за вынесения большей части логики из языка.

Мне не нравится в теме то, что ты транслируешь и ограничиваешь своё понимание той протухшей действительностью.

Ты прости, что я на тебя гоню - просто ты должен понимать - я уже не могу просто вести себя спокойно с той аудиторией, что постоянно атакует меня.

ты прав в той системе аксиом которые в данной дискуссии продвигаеш

Ну это естественно, ибо должен же я что-то внятное писать и представлять, иначе буду очередным балаболом.

AnonCxx
()
Ответ на: комментарий от anonymous
/* test.c */

#include <stdio.h>
#include <stdlib.h>

int f()
{
    printf("hello\n");
    exit(0);
}

int main()
{
    return f();
}
$ gcc -std=c89 --pedantic-errors -Wall -Wextra test.c -o test
$ ./test
hello
$ 

ни ошибок, ни предупреждений

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

Самый правильный выход из main() — return. А exit в main только маньяки пихают! Тем паче, как я уже говорил, gcc с опциями -Wall -Werror -Wextra тупо пошлет тебя лесом за то, что ты в конце main не впихнул return! И правильно сделает!!!

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

Я тебе об этом:

gcc -Wall -Werror -Wextra 1.c 
1.c: В функции <<main>>:
1.c:13:1: ошибка: control reaches end of non-void function [-Werror=return-type]
cc1: all warnings being treated as errors


cat 1.c
#include <stdio.h>
#include <stdlib.h>

int f()
{
    printf("hello\n");
    exit(0);
}

int main()
{
    f();
}

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

Никогда. Здесь процент идиотов или маньяков среди модераторов за последнее время настолько возрос, что превысил количество нормальных людей!

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

Если хочешь общения — пиши на мыло или комментируй мою ЖЖшку. Еще я есть на элхе, казусе и изыдиэлектрониксе. Также есть на гетцклубе, но там я нечасто торчу.

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

Ясно.

На самом деле бросил бы принципы и пришел — было бы норм.

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

если просто [] то это синтаксически *

Та дырявая логика уже давно протухла. Уже лет 25 как это не так.

если [const] то это синтаксически резервирование места в пространстве смещений

Смещения тут не причём - смещения - это уже про интерфейс доступа. Любой объект обладает каким-то объёмом, который он занимает при определение внутри любого пространства. При этом массив даже не хозяин своих значений(памяти).

про union - пока их не добавили в язык явно - обходились наложением полей - от того то и пространство имён полей записей в Си не вложенно в структуру а общее у всех структур -

Опять же - это протухшая логика. Эта логика - следствие дырявости самого языка и это лет 25+ уже не так.

забавно как «ТЫ» защищая Си испозуешь о Си представление как о языке Вирт-школы с чёткой проработаностью «концепций»

Концепция, проработанность, чёткость - эти понятия не совместимы со всем к чему прикасался вирт. Фу.

То, что си дырявый - это не делает его не чётким, либо ещё чем-то. У него есть концепция - она была слишком широкой, а основная часть логики было вынесено из языка.

Нельзя было тогда реализовать концепцию языка, которая обладала бы той же мощностью, но при этом была бы строгой.

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

а си не имел годного рекурсивного чёткого определения первые ~20 лет своей юности(включая перинатальный период)(см Гайя Стила кста и желательно первое издание начала 80ых если сможешь найти)

Это не важно. Из этого ничего не следует. Сейчас другой си.

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

Ну да, в спорах со мною вылезает неосведомлённость некоторых ораторах в тех темах, о которых они пытаются рассуждать и в рамках которых пытаются оспаривать мои утверждения.

Я бы отвечал вам нормально, но вы какие-то слишком наглые. Я просто принципиально не приемлю такое отношение.

Если ты чего-то не понял, либо с чем-то не согласен - ответь нормально. «Царь, на каком основании ты сделал это утверждение?» - я тебе спокойно отвечу, - на основании того, что в современном си на уровне стандарта закреплено то, что «main возвращает» 0. А ручное return 0; требуется в си 80-х годов.

Но такая логика с вами не работает, ибо если я это спрошу у тебя - ты мне не ответишь. Поэтому я должен выкатывать контраргументы сразу, ибо в противном случае в ответ ничего кроме «царь дурак» - я не услышу.

AnonCxx
()
Ответ на: комментарий от anonymous
mikhail@less /tmp $ cat test.c
void foo()
{
}

int main(void)
{
        foo(1, 2, 3);
        return 0;
}
mikhail@less /tmp $ gcc -Wall -Wpedantic test.c
mikhail@less /tmp $ cat test.cpp
void foo()
{
}

int main()
{
        foo(1, 2, 3);
        return 0;
}
mikhail@less /tmp $ g++ -Wall -Wpedantic test.cpp 
test.cpp: В функции «int main()»:
test.cpp:7:20: ошибка: too many arguments to function «void foo()»
         foo(1, 2, 3);
                    ^
test.cpp:1:6: замечание: declared here
 void foo()
      ^
Deleted
()
Ответ на: комментарий от AnonCxx

в современном си на уровне стандарта закреплено то, что «main возвращает» 0. А ручное return 0; требуется в си 80-х годов.

Насрать мне на «современный си»! Я пишу на нормальном си, а не хрен-те каком. А нормальный, «керниганскоричевский», си требует return 0. И вообще, если функция имеет тип, return в ней обязательно должен быть.

Вот ежели ты напишешь void main(), то хрен с тобой. Но это — извращение, ибо правильно писать int main(int a, char **v), да и параметры командной строки в 99.9% случаев используются.

Я себе вот такую штуку сделал, чтобы было проще с аргументами работать (+ она позволяет обрабатывать параметры с параметрами, а также употреблять множественные параметры, скажем, -vvv даст соответствующему инту значение 3, а просто -v — один; что-то вроде -i файл_1 -i файл_2 -i файл_3 создаст список из трех имен и т.д., и т.п.).

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

Тут и со мной будет уныло, потому что помимо модераторского произвола последнее время еще и вопросы какие-то идиотские задают: то про хрюникод, то про поцтерошлак, то про бубунты какие-нибудь. Мне туда соваться — только бан зарабатывать и попусту спорить с идиотами, которые считают поцтерошлак благом…

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

С/С++-счик

Ну ты загнул! Между С и С++ разница как между паскалем и пхытоном! Абсолютно разные языки с абсолютно разными парадигмами! И тот, кто считает их одинаковыми, на самом деле вообще ни С, ни С++ не знает!

Я, например, не понимаю объекто-ориентированности, привык к гольной функциональщине, поэтому С++ вообще не разумею. У некоторых наоборот — функциональность головняк вызывает, а ООП как по маслу проходит. Тот же пхытон я даже не пытался понять, ибо ООПщина жесточайшая.

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

Ваше первоначальное утверждение было: «Это не Си». Тем не менее, Вы сами привели мне два примера (C, C++), в первом из которых программа на C успешно скомпилировалась. С тем что в C функцию, не принимающую аргументы, следует объявлять как

int f(void);
я согласен, но не с утверждением что это не валидный C код. Это был пример, не имеющий отношения к передаче параметров через заголовок.

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

Создатель языка C++ в своей книге C++ programming language в одной из вводных глав акцентирует внимание на том, что C++ не навязывает Вам ООП как единственно верную парадигму (хотя отчасти я и не согласен; стандартная библиотека - отличный пример ООП).

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

Насрать мне на «современный си»!

Ну дак а зачем ты споришь? Я там ведь написал «как там в 80-х?». Если тебе в 80-х нравится - в чём проблема?

А нормальный, «керниганскоричевский», си требует return 0. И вообще, если функция имеет тип, return в ней обязательно должен быть.

Ты пишешь не на «керниганскоричевский» си, а на первом ansic(вернее хочешь в это верить). Что же ты тогда предал «„керниганскоричевский“ си» - фтопку int main(int a, char **v) {} - даёшь int main(a, v) int a, char **v; {}

Современный си такой же ansic, только не настолько протухший.

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

Мне конечно больно попирать твою веру, но в гцц по умолчанию стоит так не любимый тебе «современный си», а ты компилируешь им свой код и тебе кажется, что у тебя там крси.

Добавь -std=c89 -pedantic, ибо в гцц даже нету кр-си настолько он протух. И твой код просто не собирается:

In file included from cmdlnopts.h:26:0,
                 from main.c:23:
parseargs.h:25:21: ошибка: лишние токены в конце директивы #include [-Werror]
 #include <stdbool.h>// bool
                     ^
In file included from cmdlnopts.h:26:0,
                 from main.c:23:
parseargs.h:36:1: ошибка: комментарии в стиле C++ не разрешены в ISO C90
 // macro for argptr
 ^
parseargs.h:36:1: ошибка: (об этом будет сообщено только один раз для каждого файла)
In file included from cmdlnopts.h:26:0,
                 from main.c:23:
parseargs.h:124:8: ошибка: лишние токены в конце директивы #endif [-Werror=endif-labels]
 #endif // __PARSEARGS_H__
        ^
In file included from main.c:23:0:
cmdlnopts.h:31:1: ошибка: комментарии в стиле C++ не разрешены в ISO C90
 // parameters of mirror
 ^
cmdlnopts.h:31:1: ошибка: (об этом будет сообщено только один раз для каждого файла)
cmdlnopts.h:60:8: ошибка: лишние токены в конце директивы #endif [-Werror=endif-labels]
 #endif // __CMDLNOPTS_H__
        ^
main.c: В функции «parse_filter»:
main.c:39:34: ошибка: инициализирующий элемент не может быть вычислен во время компоновки [-Werror=pedantic]
   {"type", NEED_ARG, arg_string, &params.filtertype},
                                  ^
main.c:39:3: ошибка: инициализирующий элемент не может быть вычислен во время компоновки [-Werror=pedantic]
   {"type", NEED_ARG, arg_string, &params.filtertype},
   ^
main.c:40:31: ошибка: инициализирующий элемент не может быть вычислен во время компоновки [-Werror=pedantic]
   {"xsz",  NEED_ARG, arg_int, &params.xsize},
                               ^
main.c:40:3: ошибка: инициализирующий элемент не может быть вычислен во время компоновки [-Werror=pedantic]
   {"xsz",  NEED_ARG, arg_int, &params.xsize},
   ^
main.c:41:31: ошибка: инициализирующий элемент не может быть вычислен во время компоновки [-Werror=pedantic]
   {"ysz",  NEED_ARG, arg_int, &params.ysize},
                               ^
main.c:41:3: ошибка: инициализирующий элемент не может быть вычислен во время компоновки [-Werror=pedantic]
   {"ysz",  NEED_ARG, arg_int, &params.ysize},
   ^
main.c: В функции «main»:
main.c:52:23: ошибка: комментарии в стиле C++ не разрешены в ISO C90
  glob_pars *G = NULL; // default parameters see in cmdlnopts.c
                       ^
main.c:52:23: ошибка: (об этом будет сообщено только один раз для каждого файла)
main.c:76:3: ошибка: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
   int i = 0;
   ^~~
main.c:101:3: ошибка: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
   char **fpars = G->filter;
   ^~~~
cc1: all warnings being treated as errors
make: *** [<встроенное>: main.o] Ошибка 1

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

С/С++ - это сишный диалект из С++ т.к. си основан на кастрированном с90(либо что-то типа того).

В этом диалекте f() заменено на f(...), f(void) на f() и f(void), вырублен автокаст для воид, вырублен свободный каст и прочее.

Именно этот кастрированный вариант си и «знают» подавляющие большинство тех, кто считает что он знает си.

Так же под С/С++ понимают сишный диалект из С++, но с классами. Либо ещё с чем-то.

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

А если ошибка - то ретернить 1 надо

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

Ну это естественно, ибо должен же я что-то внятное писать и представлять, иначе буду очередным балаболом.

Так ты и есть балабол. Зубрил бы свой стандарт тихо в уголке и помогал бы первокурсникам лабы делать в соотвестующих темах, и претензий к тебе бы не было. Но ты же в каждой бочке затычка.

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

Ничего сложного. Для базового уровня (чтобы хотя бы понимать что происходит) достаточно денёк посидеть. Вооружись книжкой по архитектуре ЭВМ и почитай азы информатики, если очень сложно и за день не начинаешь понимать.

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

оставляя в стороне как в реальности выглядит слон о котором спорят 7 мудрецов

стоит всёж иметь понимание на эволюцию и отличия Си разных эпох.

и так вот начиная с анси (т.е 89/90) со всеми остановками 99? 11 Си ужо давно как зарейдин корпорациями и самим комитетом по языку как самостоятельной бюрократической сущьностью.

и даже мануал K&R даёт не так много к пониманию индивидуальности Си (при условии что падаван уже понимать какой угодно ипреративный язык с к «стандартным» набором агрегирования данных и «стандартным» методом декомпозиции ака функции/процедуры и аргументы к ним) как сырцы 70/80 годов

в этом очень пользительны сырцы http://minnie.tuhs.org/cgi-bin/utree.pl?file=V2/lib/printf.c (как пример)

т.е Си это не «единственное» а одно из ряда as|сс|sh|ed|dc|make|awk|yacc|troff языков_инструментов

т.е сама серебреная пуля регулярки+упрощённаяОсь оказалась настолько мощной что и не важен в каком(насколько безглючном и логичном) синтаксисе реализованнны сами инструменты -

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

Да я пробовал уже, и даже что-то писал

Мало пробовал.

Программистом стать очень легко. Выбираешь кучу говна побольше и ныряешь. Через десять лет выныриваешь с криком: «Эврика! Я понял как это работает!», и идешь к дяде на работу. Он тебе дает другую кучу говна, и ты делаешь тоже самое, только за деньги.

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

Коды возврата тут пожалуй самое главное, а придраться можно абсолютно к любому коду, даже если сделаешь по всем правилам всегда можно сказать «переусложнил», «нептимально» и т.д. при желании.

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

с этим соглашусь. но в остальном вы тут такой холивар устроили на ровном месте, что нещасный пингвин уже в панике от заморочек сишечки.

вряд ли сейчас кто-то начинает с ассемблера. мы начинали, потому что ничего не было просто. поэтому дебри реализации работы с указателями в компиляторе начинающему вряд ли нужны. это потом он может ковыряться в деталях, если сильно захочет.

на практике же синтаксис с массивом используется редко. пожалуй, я даже не видела реальных примеров в проектах. проще везде в функциях использовать указатели.

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.