Где C не является подмножеством C++? [закрытый]

Много больших ответов до сих пор: простой, эффективный, и изящный!

я предполагаю, что приложение несколько подобно лотерее, в котором каждый пользователь получает карту царапины и использует ее для выяснения у приложения, если "он уже выигран!" Так, С той точки зрения, несколько новых проблем приходят на ум:

набор номера войны , или его эквивалентный Интернет: пользователь жулика может неоднократно поражать Ваше приложение, говорить предположение каждого 10-разрядного числа по очереди? Если это - возможность, рассмотрите ограничение количества попыток от конкретного местоположения. Эффективный путь мог бы быть просто, чтобы отказаться отвечать на больше, чем, скажем, одна попытка каждые 5 секунд от того же IP-адреса. Это делает управляемые машиной нападения неэффективными и избегает проблема локаута .

проблема Локаута : при блокировке учетной записи постоянно после какого-либо количества неудачных попыток Вы подвержены к отказ в обслуживании нападения. Взломщик выше мог эффективно заблокировать каждый пользователь , если Вы не активируете аккаунты после промежутка времени. Но это - проблема, только если Ваши PIN состоят из очевидной конкатенации идентификатора пользователя + Ключ, потому что взломщик мог попробовать каждый ключ за данный идентификатор пользователя. Та техника также уменьшает Ваше ключевое пространство решительно, потому что только несколько цифр PIN действительно случайны. С другой стороны, если PIN является просто последовательностью случайных цифр, локаут должны только быть примененным к исходному IP-адресу. (Если бы попытка перестала работать, никакая действительная учетная запись не затронута, поэтому что Вы "заблокировали" бы?)

Хранение данных : если Вы действительно создаете своего рода подобную лотерее систему Вы только потребность сохранить PIN победы ! Когда пользователь вводит PIN-код, можно искать относительно маленький список PIN/призов (или эквивалент). Можно рассматривать "потерю" и недопустимые PIN тождественно с "Извините, лучшей удачей в следующий раз" сообщение или приз "по умолчанию", если экономика является правильной.

Удачи!

111
задан MD XF 12 May 2017 в 20:32
поделиться

11 ответов

Если вы сравните C89 с C ++ , то вот пара вещей

Нет предварительных определений в C ++

int n;
int n; // ill-formed: n already defined

int [] и int [N] несовместимо (нет совместимых типов в C ++)

int a[1];
int (*ap)[] = &a; // ill-formed: a does not have type int[]

Нет стиля определения функции K&R

int b(a) int a; { } // ill-formed: grammar error

Вложенная структура имеет область видимости класса в C ++

struct A { struct B { int a; } b; int c; };
struct B b; // ill-formed: b has incomplete type (*not* A::B)

Нет по умолчанию int

auto a; // ill-formed: type-specifier missing

C99 добавляет множество других случаев

Нет специальной обработки спецификаторов объявления в измерениях массивов параметров

// ill-formed: invalid syntax
void f(int p[static 100]) { }

Нет массивов переменной длины

// ill-formed: n is not a constant expression
int n = 1;
int an[n];

Нет гибкого элемента массива

// ill-formed: fam has incomplete type
struct A { int a; int fam[]; }; 

Нет ограничителя для помощи при анализе псевдонимов

// ill-formed: two names for one parameter?
void copy(int *restrict src, int *restrict dst);
133
ответ дан 24 November 2019 в 02:59
поделиться

В C ++ также есть новые ключевые слова. Ниже приведен действительный код C, но он не будет компилироваться под C ++:

int class = 1;
int private = 2;
int public = 3;
int virtual = 4;
36
ответ дан 24 November 2019 в 02:59
поделиться

В C sizeof ('a') равно sizeof (int) .

В C ++ sizeof ('a') равно sizeof (char) .

48
ответ дан 24 November 2019 в 02:59
поделиться

Здесь много чего. Просто простой пример (этого должно быть достаточно, чтобы доказать, что C не является правильным подмножеством C ++):

int* test = malloc(100 * sizeof(int));

должен компилироваться на C, но не на C ++.

20
ответ дан 24 November 2019 в 02:59
поделиться

В C ++, если вы объявляете struct , union или enum , их имя становится немедленно доступным без каких-либо квалификаторов. :

struct foo { ... };
foo x; // declare variable

В C это не сработает, потому что объявленные таким образом типы живут в своих собственных отдельных пространствах имен. Таким образом, вы должны написать:

struct foo { ... };
struct foo x; // declare variable

Обратите внимание на присутствие struct во второй строке. Вы должны сделать то же самое для union и enum (используя соответствующие ключевые слова) или использовать трюк typedef :

typedef struct { ... } foo;
foo x; // declare variable

Следовательно, у вас может быть несколько типы различных типов, названные одинаково в C, поскольку вы можете устранить неоднозначность:

struct foo { ... };
typedef enum { ... } foo;

struct foo x;
foo y;

Однако в C ++, хотя вы можете префикс имени struct с помощью ключевого слова struct всякий раз, когда вы на него ссылаетесь, пространства имен объединены, и поэтому приведенный выше фрагмент C недействителен. С другой стороны, C ++ специально делает исключение, позволяющее типу и typedef для этого типа иметь одно и то же имя (очевидно, без эффекта), чтобы разрешить использование трюка typedef без изменений по сравнению с C.

16
ответ дан 24 November 2019 в 02:59
поделиться

Это также зависит от того, какую разновидность C вы используете. Страуструп сделал C ++ максимально совместимым и не более совместимым со стандартами ANSI 1989 и ISO 1990 года, и версия 1995 года ничего не изменила. Комитет C пошел в несколько ином направлении со стандартом 1999 года, и комитет C ++ изменил следующий стандарт C ++ (вероятно, выйдет в следующем году или около того), чтобы соответствовать некоторым изменениям.

Страуструп перечисляет несовместимости с C90 / C95 в Приложении B.2 к Специальному выпуску «Язык программирования C ++» (третье издание с некоторыми добавленными материалами):

'a' - это int в C, a char в C ++.

Размер перечисления составляет int в C, не обязательно в C ++.

C ++ имеет // комментарии до конца строки, C не делает t (хотя это обычное расширение).

В C ++ определение struct foo { помещает foo в глобальное пространство имен, в то время как в C оно должно называться struct foo . Это позволяет определению структуры скрывать имя во внешней области видимости и имеет несколько других последствий. Кроме того, C допускает большую область для определений struct и допускает их в объявлениях типа возвращаемого значения и типа аргумента.

C ++ более суетлив с типами в целом. Он не позволяет назначать целое число объекту enum , а объекты void * не могут быть назначены другим типам указателей без приведения. В C можно обеспечить избыточный инициализатор ( char name [5] = "David" , где C отбрасывает завершающий нулевой символ).

C89 допускает неявное int во многих контекстах, а C ++ - нет. Это означает, что все функции должны быть объявлены на C ++, в то время как в C89 часто можно было обойтись, приняв int для всего, что применимо в объявлении функции.

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

C более либерален в отношении внешних ссылок. В C глобальная переменная const неявно является extern , а в C ++ это неверно. C позволяет несколько раз объявлять объект глобальных данных без extern , но это неверно в C ++.

Многие ключевые слова C ++ не являются ключевыми словами в C или являются #define d в стандартных заголовках C.

Есть также некоторые старые особенности C, которые больше не считаются хорошим стилем. В C вы можете объявить функцию с определениями аргументов после списка аргументов. В C объявление типа int foo () означает, что foo () может принимать любое количество аргументов любого типа, а в C ++ это эквивалентно int foo (void ) .

Кажется, это охватывает все, что было от Страуструпа.

8
ответ дан 24 November 2019 в 02:59
поделиться

Единственное самое большое различие, которое я думаю, заключается в том, что это действительный исходный файл C:

int main()
{
    foo();
}

Обратите внимание, что я не нигде не объявляется foo .

Помимо языковых различий, C ++ также вносит некоторые изменения в библиотеку, унаследованную от C, например, некоторые функции возвращают const char * вместо символ * .

4
ответ дан 24 November 2019 в 02:59
поделиться
#include <stdio.h>

int new (int n) {
    return n/2;
}

int main(void) {
    printf("%d\n", new(10));
    return 0;
}

См. Также раздел часто задаваемых вопросов по C ++ .

4
ответ дан 24 November 2019 в 02:59
поделиться

Компиляторы C обычно позволяли немного срезать углы, чего не допускает C ++. C ++ намного строже, чем C. И, как правило, некоторые из этих различий зависят от компилятора. g ++ допускает некоторые вещи, которые, например, не позволяет компилятору Intel C ++. Даже хорошо написанный код C не будет компилироваться с современным компилятором C ++.

-2
ответ дан 24 November 2019 в 02:59
поделиться

Вы не можете сравнивать языки только по синтаксису. Если вы это сделаете, возможно, вы увидите C как подмножество C ++. На мой взгляд, того факта, что C ++ объектно-ориентированный (а C - нет), достаточно, чтобы сказать, что C и C ++ - разные языки.

-2
ответ дан 24 November 2019 в 02:59
поделиться

Если вы используете gcc, вы можете использовать предупреждение -Wc ++ - compat , чтобы вывести предупреждения о коде C, который в некотором роде сомнителен в C ++. В настоящее время он используется в самом gcc, и в последнее время он стал намного лучше (возможно, попробуйте ночную версию, чтобы получить лучшее, что вы можете).

(Это не совсем ответ на вопрос, но людям это может понравиться).

4
ответ дан 24 November 2019 в 02:59
поделиться