Hacker Newsnew | past | comments | ask | show | jobs | submit | piesquaredarr's commentslogin

Huh, I never realized that C++ standards were removing C features. Time to be more careful about using g++ for everything.


C++ has never been a strict superset of C. The most obvious example is the "class" and "new" keywords which can be used as an identifier in C, but not in C++. There's more subtle differences as well, such as character literals having type int in C and char in C++.


Another really common one is that casting from void * to any other type doesn't require a cast in C, but it does in C++:

  #include <stdlib.h>

  int main()
  {
    int *foo = malloc(sizeof(int));
    return 0;
  }
That works in C, but not in C++.

There's actually another subtle different in there that main() means "unspecified arguments" in C, and "no arguments" in C++. ("No arguments" in C would be main(void).) However, it's no longer commonly used that way in C, but casts from void * to other types is very common in C.


The `func()` vs `func(void)` difference has been deprecated for a while, and is removed in C23.


Using unions for type punning is legal C, but the exact same code has UB in C++

The modern C++ way to do this ~safely isn't legal C, and yet the type pun isn't safe in C++. I believe using memcpy() to launder the bits is legal in both languages and in some cases your compiler can figure out what you're doing and not actually emit the unnecessary copy.


I used a few different compilers for C in one project. Ended up at memcpy and byteswaping to get data between different instances of the code correctly (some ARM, mips, and x86, and each of those can set the byte order). Using a union is possible if it supports packing and the bytes happen to be in the same order and the compiler keeps the struct in the same order. I found that is not true of all compilers, by default. Massively annoyed having to rewrite about 50 file writes/reads that were nice and simple with massive memcpy cascades. Inside the same code on the same compiler you can get away with a lot of things. But port to another arch or try to get bin data out of your program into another (good luck). These days there are realistically 4 compilers people use and they tend to behave mostly the same, also nice libs that do most of this for you. That was the same project I learned not all printf's are created equal. Different CRTs do very different things even in the same compiler family. There is a reason everyone decided to use json and xml to transport data. Because of that mess.


Ah, what an elegant example, haha.


Using g++ for C code is a recipe to get badly burnt - for unrelated reasons. Trigraphs are disabled in gcc by default anyway.


That's true for any C++ compiler, really. Although C++ tries to retain some element of compatibility with C, there have always been differences (you can name a variable `class` in C but not in C++).


By default, GCC ignores trigraphs in C code too.

You have to explicitly pass -std=c17 (or whatever) to get standard-conforming behavior including trigraphs.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: