Встроенные компиляторы C позволяют использовать void main (), потому что может не быть какой-либо операционной системы, которой можно было бы передать код возврата.
Жанна Пиндар
26
Как можно так часто голосовать за такой вопрос? Это действительно не так интересно ... Я имею в виду, что строки - это массивы, а массивы - указатели - это действительно старая шляпа в C, не так ли?
Феликс Домбек
64
@Felix, это кратко написанный вопрос, который устраняет общую путаницу для новичков в этом языке. SO не только для экспертов - это также для новичков, и подобные целевые вопросы хороши для направления новичков в будущем.
bdonlan
37
@ Феликс: Вы ошибаетесь. массивы не являются указателями
Джон Диблинг
Ответы:
209
Вы сравниваете два адреса памяти для разных строк, которые хранятся в разных местах. По сути, это выглядит так:
if(0x00403064==0x002D316A)// Two memory locations{
printf("Yes, equal");}
Используйте следующий код для сравнения двух строковых значений:
Кроме того, "a" == "a"действительно может возвращать истину, в зависимости от вашего компилятора, который может объединять одинаковые строки во время компиляции в одну для экономии места.
Когда вы сравниваете два символьных значения (которые не являются указателями), это числовое сравнение. Например:
GCC также имеет параметры -fmerge-constantsи -fno-merge-constantsдля включения / отключения слияния строк и констант с плавающей запятой в единицах перевода, хотя в некоторых GCC кажется, что слияние констант всегда включено независимо от этой опции.
Адам Розенфилд
2
Это сработает, если вы используете «а» вместо «а». Первый - это символ, который на самом деле является числовым значением.
GolezTrol
@GolezTrol: в C буквальный "a" действительно имеет intтип. :-) Кроме того, указатели не обязательно должны быть числовыми значениями.
Bastien Léonard
intтоже числовое, не так ли? Но я думал, что символы были байтами. Int - 4 байта. Сами указатели тоже целочисленные. Они содержат адрес группы данных (данные, которые действительно не обязательно должны быть числовыми).
GolezTrol
'a' == 'A' // not true... MySQL требует отличия.
Стивен
52
Я немного опоздал на вечеринку, но все равно отвечу; технически те же биты, но с немного другой точки зрения (язык C ниже):
В языке C это выражение "a"обозначает строковый литерал , который является статическим безымянным массивом const char, длиной два - массив состоит из символов 'a'и '\0'- завершающий нулевой символ сигнализирует о конце строки.
Однако в C точно так же вы не можете передавать массивы функциям по значению - или присваивать им значения ( после инициализации ) - ==для массивов нет перегруженного оператора , поэтому сравнивать их напрямую невозможно. Рассматривать
int a1[]={1,2,3};int a2[]={3,4,5};
a1 == a2 // is this meaningful? Yes and no; it *does* compare the arrays for// "identity", but not for their values. In this case the result// is always false, because the arrays (a1 and a2) are distinct objects
Если ==он не сравнивает массивы, что тогда он на самом деле делает? В C почти во всех контекстах, включая этот, массивы распадаются на указатели (которые указывают на первый элемент массива), и сравнение указателей на равенство делает то, что вы ожидаете. Так эффективно, делая это
"a"=="a"
вы фактически сравниваете адреса первых символов в двух безымянных массивах . Согласно стандарту C, сравнение может дать истинное или ложное значение (т.е. 1 или 0) - "a"s может фактически обозначать один и тот же массив или два совершенно не связанных массива. С технической точки зрения результирующее значение не указано , что означает, что сравнение разрешено (т. Е. Это не неопределенное поведение или синтаксическая ошибка), но любое значение является допустимым, и реализация (ваш компилятор) не требуется для документирования того, что на самом деле произойдет.
Как указывали другие, для сравнения «c-строк» (т.е. строк, оканчивающихся нулевым символом) вы используете вспомогательную функцию, strcmpнайденную в стандартном файле заголовка string.h. Функция имеет возвращаемое значение 0для одинаковых строк; считается хорошей практикой явно сравнивать возвращаемое значение с 0вместо использования оператора `! ´, т.е.
strcmp(str1, str2)==0// instead of !strcmp(str1, str2)
Не указано, являются ли эти массивы различными, если их элементы имеют соответствующие значения .
Таким образом, в этом случае не указано, различны ли оба "a"s. Оптимизированный компилятор может хранить один "a"файл только для чтения, и обе ссылки могут относиться к нему.
Потому что это 2 отдельных const char*указателя, без фактических значений. Вы говорите что-то вроде того, 0x019181217 == 0x0089178216что конечно возвращает НЕТ
Строковые литералы - это не указатели, это массивы. Однако при сравнении они превращаются в указатели.
GManNickG
@Gman правда, извините за то, что не совсем ясно об этом, как правило, забываю об этом :)
Antwan van Houdt
9
Проще говоря, в C нет встроенного оператора сравнения строк. Таким образом нельзя сравнивать строки.
Вместо этого строки сравниваются с использованием стандартных библиотечных процедур, таких как strcmp (), или путем написания кода для циклического перебора каждого символа в строке.
В C строка текста в двойных кавычках возвращает указатель на строку. Ваш пример сравнивает указатели, и, очевидно, ваши две версии строки существуют по разным адресам.
Но это не сравнение самих струн, как вы, кажется, ожидаете.
Почему вы ожидаете, что строки будут выровнены по 4-байтовой границе? Они не целые. 2 - это то, что я ожидал (если компилятор не объединяет их), поскольку каждая строка имеет длину два байта, включая нулевой терминатор.
Сергей Таченов
Некоторая степень выравнивания может, например, позволить strcmpзапускать несколько байтов за раз. Некоторые компиляторы делают это, некоторые нет, некоторые делают это только для строк длиннее минимума ...
zwol
@Zack: как они узнают длину строки, прежде чем сравнивать их?
Joachim Sauer
Я имел в виду, что некоторые компиляторы выравнивают строки длиннее минимума.
zwol
1
Вы сравниваете два адреса памяти, поэтому результат не всегда будет правдой. Вы пробовали if('a' == 'a'){...}?
Символы занимают только 1 байт, но символьные литералы, такие как 'a', на самом деле являются целыми числами.
Spidey
0
В некоторых компиляторах есть опция «объединить строки», которую можно использовать, чтобы заставить все константные строки иметь один и тот же адрес. Если бы вы использовали это, "a" == "a"было бы true.
void main
??? Фу ...Ответы:
Вы сравниваете два адреса памяти для разных строк, которые хранятся в разных местах. По сути, это выглядит так:
Используйте следующий код для сравнения двух строковых значений:
Кроме того,
"a" == "a"
действительно может возвращать истину, в зависимости от вашего компилятора, который может объединять одинаковые строки во время компиляции в одну для экономии места.Когда вы сравниваете два символьных значения (которые не являются указателями), это числовое сравнение. Например:
источник
-fmerge-constants
и-fno-merge-constants
для включения / отключения слияния строк и констант с плавающей запятой в единицах перевода, хотя в некоторых GCC кажется, что слияние констант всегда включено независимо от этой опции.int
тип. :-) Кроме того, указатели не обязательно должны быть числовыми значениями.int
тоже числовое, не так ли? Но я думал, что символы были байтами. Int - 4 байта. Сами указатели тоже целочисленные. Они содержат адрес группы данных (данные, которые действительно не обязательно должны быть числовыми).'a' == 'A' // not true
... MySQL требует отличия.Я немного опоздал на вечеринку, но все равно отвечу; технически те же биты, но с немного другой точки зрения (язык C ниже):
В языке C это выражение
"a"
обозначает строковый литерал , который является статическим безымянным массивомconst char
, длиной два - массив состоит из символов'a'
и'\0'
- завершающий нулевой символ сигнализирует о конце строки.Однако в C точно так же вы не можете передавать массивы функциям по значению - или присваивать им значения ( после инициализации ) -
==
для массивов нет перегруженного оператора , поэтому сравнивать их напрямую невозможно. РассматриватьЕсли
==
он не сравнивает массивы, что тогда он на самом деле делает? В C почти во всех контекстах, включая этот, массивы распадаются на указатели (которые указывают на первый элемент массива), и сравнение указателей на равенство делает то, что вы ожидаете. Так эффективно, делая этовы фактически сравниваете адреса первых символов в двух безымянных массивах . Согласно стандарту C, сравнение может дать истинное или ложное значение (т.е. 1 или 0) -
"a"
s может фактически обозначать один и тот же массив или два совершенно не связанных массива. С технической точки зрения результирующее значение не указано , что означает, что сравнение разрешено (т. Е. Это не неопределенное поведение или синтаксическая ошибка), но любое значение является допустимым, и реализация (ваш компилятор) не требуется для документирования того, что на самом деле произойдет.Как указывали другие, для сравнения «c-строк» (т.е. строк, оканчивающихся нулевым символом) вы используете вспомогательную функцию,
strcmp
найденную в стандартном файле заголовкаstring.h
. Функция имеет возвращаемое значение0
для одинаковых строк; считается хорошей практикой явно сравнивать возвращаемое значение с0
вместо использования оператора `! ´, т.е.источник
Согласно C99 (Раздел 6.4.5 / 6)
Таким образом, в этом случае не указано, различны ли оба
"a"
s. Оптимизированный компилятор может хранить один"a"
файл только для чтения, и обе ссылки могут относиться к нему.Посмотрите вывод на gcc здесь
источник
Потому что это 2 отдельных
const char*
указателя, без фактических значений. Вы говорите что-то вроде того,0x019181217 == 0x0089178216
что конечно возвращает НЕТИспользуйте
strcmp()
вместо==
источник
Проще говоря, в C нет встроенного оператора сравнения строк. Таким образом нельзя сравнивать строки.
Вместо этого строки сравниваются с использованием стандартных библиотечных процедур, таких как strcmp (), или путем написания кода для циклического перебора каждого символа в строке.
В C строка текста в двойных кавычках возвращает указатель на строку. Ваш пример сравнивает указатели, и, очевидно, ваши две версии строки существуют по разным адресам.
Но это не сравнение самих струн, как вы, кажется, ожидаете.
источник
Указатели.
Первый
"a"
- это указатель на строку ASCII с завершающим нулем.Второй
"a"
- указатель на другую строку ASCII с завершающим нулем.Если вы используете 32-битный компилятор, я бы ожидал
"a"=="a"-4
. Я только что попробовал с tcc / Win32, и у меня получилось"a"=="a"-2
. Ну что ж...источник
strcmp
запускать несколько байтов за раз. Некоторые компиляторы делают это, некоторые нет, некоторые делают это только для строк длиннее минимума ...Вы сравниваете два адреса памяти, поэтому результат не всегда будет правдой. Вы пробовали
if('a' == 'a'){...}
?источник
этот вопрос дает очень хорошее объяснение всем начинающим ....
позвольте мне также внести свой вклад в это .....
как все выше объясняли, почему вы получаете такой результат.
теперь если хочешь свою прогу. Чтобы вывести «да равно», тогда
либо использовать
или
не используйте "a" как строки, используйте их как символы ....
в символах C - это короткое целое число размером 1 байт .......
источник
'a'
, на самом деле являются целыми числами.В некоторых компиляторах есть опция «объединить строки», которую можно использовать, чтобы заставить все константные строки иметь один и тот же адрес. Если бы вы использовали это,
"a" == "a"
было быtrue
.источник
если сравнение между символами всегда в одинарных кавычках, например
и C не может поддерживать сравнение строк, например
"abc" == "abc"
Это сделано с
strcmp("abc","abc")
источник
Этот парень не использует переменные. Вместо этого он временно использует текстовые массивы:
a
иa
. Причина почемуне работает конечно, это то, что вы не сравниваете переменные.
Если бы вы создали такие переменные, как:
то вы могли бы сравнить
text
сtext2
, и это должно быть правдойМожет не стоит забывать использовать
{
и}
=)источник