LINUX.ORG.RU

Использование глобальных const char*

 


0

1

Будет ли такой код считаться хорошим подходом ?

static const char* gvar = NULL; //Здраво ли так объявлять глобальные char* ?
 
void func(){
 
    char path[4096];
    snprintf(path, sizeof(path), "%s%s", gvar, " - continued string ");
    
    printf ("String = %s\n", path);
}
 
int main(int argc, char *argv[]) {
 
    // .............
    if (gvar) {
        gvar = "One String";
    } else {
        gvar = "Second String";
    }
    // ............
 
    int my_condition = 1; // или 0
 
    if (my_condition) gvar = "Third String"; // просто пример, чтобы не раздувать код лишним
    func();
    return 0;
}

Есть ли вероятность , что моя строка gvar , затрется где когда нибудь другой белибердой ?

Ответ на: комментарий от FreakMurderer

А чем , плох мой пример, ну вот чем

Тем, что глобальная переменная может изменится где угодно, как ты найдёшь это место в коде? Т.е. почему-то в твоей переменной ВНЕЗАПНО записано «fail», и как ты будешь искать, кто туда записал? А если там NULL, то программа просто рухнет. А может не рухнет.

emulek
()

Совет от человека с ООП головного мозга

Тут тебе много что сказали по поводу глобальной переменной, но есть вариант оставить глобальную переменную и при этом разрулить к ней доступ. Сделай функции для работы с этой переменной - получения значения и апдейта этого значения. Напиши в них логику, может быть когда-то стоит запрещать изменять значение. Вынеси сигнатуры функций в заголовочный файл, а реализацию - в отдельный c-файл, а саму переменную сделай в нем глобальной, но при этом static. Тогда она будет локальна для этого С-файла. Обращайся к ней в любом месте через созданные функции, достаточно будет сделать #include этого заголовочного файла. Ну да, с объектным файлом, результатом компиляции этого отдельного C-файла тебе все остальное придется линковать.

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

А я вот не хочу заниматься лишней работой ..

эта работа окупится сторицей во время поддержки. Пока у тебя 100 строк, то всё просто, но начиная с 1000 строг глобальные — ад и израиль.

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

Ну, коли тебе хочется — используй. Никто ж не запрещает!

ну если код не пойдёт дальше локалхоста — да.

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

Вот я и об этом спрашиваю, кто или что может изменить эти постоянные ? Есть пример ?

у тебя константное содержимое указателя, сам указатель можно изменять. Кроме того есть такая штука, как каст.

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

Еще раз - читайте всю ветку внимательно, все намного проще...

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

глобальные переменные нельзя использовать НИКОГДА ? Так ?

да. Именно потому на bash'е нельзя писать что-то больше 200 строк. Никто не запрещает, просто сам программист запутается в глобальных переменных, а без них в bash'никуда не деться.

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

Переменная читается только в одном си файле, в хидере ее нет смысла объявлять...

emulek - я тебе не верю что-то, можешь не писать сюда больше ))

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

Иначе никак не выйдет сделать.

да, тут проще сделать структуру с кучей флагов. И торжественно поклясться, что структуру будет только обработчик менять.

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

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

про static переменные в функциях ты не слышал?

emulek
()

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

Еще никогда не слушай людей с «ООП» головного мозга и «глабальная пиременная-бяка!!1». Это все те же недалекие быдлокодеры, которые вместо выхода из вложенных циклов по goto городят кучи условий, потом забывают поправить одно из этих условий - ну ты понял, что их мнение бесценно и бесполезно.

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

emulek - я тебе не верю что-то, можешь не писать сюда больше ))

а стоило бы :) . emulek как ни кто другой разбирается в bash-кодинге и прочей скриптовой хрени..

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

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

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

Упс не разглядел, прошу прощения. Тогда ок, вытаскивай в отдельный модуль трансляции и все супер. Походу никто в треде это не разглядел =).

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

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

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

вместо выхода из вложенных циклов по goto городят кучи условий

``goto`` конечно можно (для выхода из цикла) — но обычно безсмысленно, так как ``return`` проще :) .. а RAII нормально отработает освобождение ресурсов :-) , если конечно речь действительно про ООП

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

Перечитайте всю ветку пожалуйста...

ты спросил про проблемы? Я ответил. Повторю:

1. сложность поддержки. Практически нереально найти место в коде, где глобальная меняется.

2. константность невозможна для _переменной_, её нельзя сделать константой в одной части кода и не константой в другой (правда можно сделать макрос, который запускает inline функцию как errno. Это плохо, но лучше чем глобальная)

3. инициализация статических — вопрос сложный.

4. функция с глобальными(или со статическими) переменными не реентабельна, в неё нельзя войти дважды. Это важно для многопоточности но и не только. Если сегодня это тебе не нужно, не факт, что завтра не придётся всё переделывать, т.е. перекопать ВЕСЬ код в поисках этой переменной.

5. сложно придумать уникальное имя, которое ТОЧНО нигде не используется.

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

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

Походу никто в треде это не разглядел =).

ды все всё разглядели :-) . глобальная переменная она и есть глобальная переменная.

если даже ты сделаешь static внутри функции — то это всё равно глобальная переменная (ну да, да, «статическая».. но один фиг — она глобальная!).

а в этой теме — единственной оправдание глобальной переменной — это только тот факт что она лишь один раз записывается и потом много раз читается (не меняется).

однако это же сразу создаёт и *лимит* : в будущем эту программу уже НЕльзя будет превратить в shared-object-библиотеку, точнее говоря превратить можно но использовать нельзя без глюков. (но сейчас, до тех пор, пока ни кто не захотел превратить эту программу в библиотеку — всё нормально проблем нет :))

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

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

ты топиком не ошибся? Мы про сишку.

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

всё нормально проблем нет :))

Ну и все !! ) Скажите еще вот что, если я объявил переменную как статик в с файле , она только в этом файле будет видна ? Если да , то мне это и нужно...

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

Походу никто в треде это не разглядел

я видел. Это всё равно плохо. Хотя если у вас 1(одна) функция на 1(один) файл, то нормально(хотя и бесполезно). И функции не больше 100 строк.

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

Да, она только в этом файле будет видна. Ключевое - на этапе линкования. Это значит, что даже объявив ее где-то в заголовке как extern, все равно к ней не получить доступ. Это именно то, почему я не возражаю против такого и только такого использования глобальных.

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

Так я про то и говорю - типа инкапсуляция. Спрятать ее и все. Еще какой-нибудь аттрибут __inline__ (не помню, есть такие?) добавить, компилятор все поинлайнит и вообще хорошо будет.

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

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

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

ты сделаешь static внутри функции — то это всё равно глобальная переменная (ну да, да, «статическая».. но один фиг — она глобальная!).

она будет глобальной тогда и только тогда, когда ты указатель на неё вернёшь наружу функции. Да и то лишь во внешней функции. Глобальность == область видимости во всей единице трансляции.

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

Да... я понял, но мне не нужен доступ с разных частей программы ...

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

> ты сделаешь static внутри функции — то это всё равно глобальная переменная (ну да, да, «статическая».. но один фиг — она глобальная!).

она будет глобальной тогда и только тогда, когда ты указатель на неё вернёшь наружу функции. Да и то лишь во внешней функции. Глобальность == область видимости во всей единице трансляции.

ты всё верно говоришь.

очевидно — я подобрал неверный термин :) ..

суть которую я хотел донести (словом «глобальная») — я имел ввиду что *поведение* *кода* который будет завязан на использовании этой переменной — будет таким, как будто этот код имеет общее глобальное состояние. («статическая» переменная — ведь как раз и будет определять это глобальное состояние поведения кода).

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

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

p.s. в треде просмотрел только первый десяток сообщений

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

А вот не факт. Ты можешь гарантировать, что увидев у нее const, да еще и static, компилятор не накрутит какую-нибудь оптимизацию по инлайну ее значения во все нужные места?

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

Еще какой-нибудь аттрибут __inline__ (не помню, есть такие?)

есть, но тебе он не поможет. Как компилятор из другого модуля будет инлайтить? Ну и inline только на функции действует, не на переменные.

Просто смысла нет особого: если модуль простой и маленький, то зачем глобальная в этом модуле? Если модуль большой и сложный, ты задолбаешься поддерживать такой говнокод.

Конечно дело твоё, если ты код один пишешь для себя.

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

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

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

будет завязан на использовании этой переменной — будет таким, как будто этот код имеет общее глобальное состояние.

угу. И это плохо. См. SICP.

Однако в сложном рекурсивном коде static неплохо экономит стек и время.

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

Ты можешь гарантировать, что увидев у нее const

ещё раз: сам указатель у тебя НЕ КОНСТАНТНЫЙ. У твоего (точнее у ТСа)указателя только содержимое константное. Сам указатель можно изменить на память в куче или даже в стеке(заполучив UB конечно). Т.ч. компилятор ничего не сможет накрутить.

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

Однако в сложном рекурсивном коде static неплохо экономит стек и время.

наверное ``static __thread`` я бы пару раз бы я поиспользовал бы :-) в таком случае (а без ``__thread`` — страшнова-то! :))

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

Можно к тебе частно обратиться, коль ты такой ярый противник глобальных переменных во всех их проявлениях, я хочу тебе дать ссылку на оригинальный код, и увидеть как бы ты решил мой вопрос.. Там много разбираться не надо, переменная всего одна , функций - 3-4 , которым она нужна... Ну так что ?

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

глобальные переменные всегда уродуют код

Профессионал в написании хелло-ворлдов с нуля детектед.

anonymous
()

Будет ли такой код считаться хорошим подходом ?

да, только лучше static const char* const gvar;

Есть ли вероятность , что моя строка gvar , затрется где когда нибудь другой белибердой ?

если не говорить про магнитные бури и пр. - нет

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

У меня (в glibc) — глобальная переменная.

ты в этом уверен? Я когда-то давно смотрел, был макрос. Как сейчас не знаю, забыл куда закопали.

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

наверное ``static __thread``

у меня тот код в многопоточности нет смысла запускать, узкое место RAM(которой нужно МНОГО, т.ч. кеши не помогают).

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

Можно к тебе частно обратиться, коль ты такой ярый противник глобальных переменных во всех их проявлениях

я их бывший сторонник. Наступил пару раз на эти грабли, теперь противник.

Но ты конечно можешь сам шишки набивать, жалко что-ли?

Там много разбираться не надо, переменная всего одна , функций - 3-4 , которым она нужна...

дык добавь параметр. Тоже const char*. Не вижу проблемы.

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

да, только лучше static const char* const gvar;

не взлетит присваивание в main(). В принципе можно массив указателей на строки, и менять индекс, типа как int main(int argc, const char* argv[])

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