Live data from Hacker News

Tell HN: C Experts Panel – Ask us anything about C

news.ycombinator.com

791–800 of 978 posts

Re: Tell HN: C Experts Panel – Ask us anything about C

#792
post #778

Earlier quoted context omitted.

I don't think we'll ever deprecate char, int, long, float, double, or size_t. ssize_t is not part of the C Standard, and hopefully never will be as it is a bit of an abomination. The main driver behind the evolution of the C Standard is not to break existing code written in C, because the world largely runs on C programs. C does provide fixed width types like uint8_t, uint16_t, uint32_t, and uint64_t. These are optio…

Those types should not be optional. CHAR_BIT needs to be 8. It is clearly possible to implement the types even on a 6502 or Alpha. From the early days of pre-ANSI C, the language supported types for which the hardware did not have appropriate word sizes. There was a 32-bit long on the 16-bit PDP-11 hardware. I would go beyond that, requiring all sizes that are a multiple of 8 bits from 8-bit through 512-bit. This bet…

> CHAR_BIT needs to be 8.

Why?

Re: Tell HN: C Experts Panel – Ask us anything about C

#793
post #123

Not a question, a request: Please make __attribute__((cleanup)) or the equivalent feature part of the next C standard. It's used by a lot of current software in Linux, notably systemd and glib2. It solves a major headache with C error handling elegantly. Most compilers already support it internally (since it's required by C++). It has predictable effects, and no impact on performance when not used. It cannot be imple…

My idea was to add something like the GoLang defer statement to C (as a function with some special compiler magic). The following is an example of how such a function could be used to cleanup allocated resources regardless of how a function returned: int do_something(void) { FILE *file1, *file2; object_t *obj; file1 = fopen("a_file", "w"); if (file1 == NULL) { return -1; } defer(fclose, file1); file2 = fopen("another…

Go-like defer() is easily implementable for C using the asm() keyword. Here's an example of how it can be done for x86: https://gist.github.com/jart/aed0fd7a7fa68385d19e76a63db687f...

Re: Tell HN: C Experts Panel – Ask us anything about C

#795

Now that C2x plans to make two's complement the only sign representation, is there any reason why signed overflow has to continue being undefined behavior? On a slightly more personal note: What are some undefined behaviors that you would like to turn into defined behavior, but can't change for whatever reasons that be?

Being brutal heterodox: STOP WRITING SIGNED ARITHMETIC.

Your code assumes that negating a negative value is positive. Your division check forgot about INT_MIN / -1. Your signed integer average is wrong. You confused bitshift with division. etc. etc. etc.

Unsigned arithmetic is tractable and should be treated with caution. Signed arithmetic is terrifying and should be treated with the same PPE as raw pointers or `volatile`.

This applies if arithmetic maps to CPU instructions, but not to Python or Haskell or etc. If you have automatic bignums, signed arithmetic is of course better.

Re: Tell HN: C Experts Panel – Ask us anything about C

#796
Hi, I'm 20 years dev and I love C. C is my second language after assembler. A good days with Turbo C with 20 MB hard drive and 8086 without IT marketing and viruses. I working on a real-time reverse-debugger for new programming platform. It's possible to debug C code and prevent NULL and memory exceptions. I create my language based on C and removed all keywords, and it works perfectly. I want to make a gcc backend to my programming language and all features will be available for any C-programs.

How I can find help for this?

Re: Tell HN: C Experts Panel – Ask us anything about C

#797
post #123

Not a question, a request: Please make __attribute__((cleanup)) or the equivalent feature part of the next C standard. It's used by a lot of current software in Linux, notably systemd and glib2. It solves a major headache with C error handling elegantly. Most compilers already support it internally (since it's required by C++). It has predictable effects, and no impact on performance when not used. It cannot be imple…

My idea was to add something like the GoLang defer statement to C (as a function with some special compiler magic). The following is an example of how such a function could be used to cleanup allocated resources regardless of how a function returned: int do_something(void) { FILE *file1, *file2; object_t *obj; file1 = fopen("a_file", "w"); if (file1 == NULL) { return -1; } defer(fclose, file1); file2 = fopen("another…

Would it make sense for defer to operate on a scope-block, sort of like an if/do/while/for block instead?

That would allow us to write:

   defer close(file);
or:

   defer {
      release_hardware();
      close(port);
   }
I feel like that syntax fits very nicely with other parts of C, and could even potentially lend itself well to some very subtle/creative uses.

I feel like a very C-like defer would:

   - Trigger at the exit of the scope-level where it was declared.

   - Be able to defer a single statement, or a scope-block.

   - Be nestable, since a defer statement just runs its target
     scope-block at the exit of the scope-block where it's defined.

   - Run successive defer statements in LIFO order, allowing later
     defer statements to still use resources that will be cleaned up
     by the earlier ones.

Re: Tell HN: C Experts Panel – Ask us anything about C

#798
post #778

Earlier quoted context omitted.

Those types should not be optional. CHAR_BIT needs to be 8. It is clearly possible to implement the types even on a 6502 or Alpha. From the early days of pre-ANSI C, the language supported types for which the hardware did not have appropriate word sizes. There was a 32-bit long on the 16-bit PDP-11 hardware. I would go beyond that, requiring all sizes that are a multiple of 8 bits from 8-bit through 512-bit. This bet…

> CHAR_BIT needs to be 8. Why?

Everything breaks if it isn't.

I was on an OS development team in the 1990s. We were using the SHARC DSP, which was naturally a word-addressed chip. Endianness didn't exist in hardware, since everything was whatever size (32, 40, or 48 bits) you had on the other end of the bus. Adding 1 to a hardware pointer would move by 1 bus width. The chip vendor thought that CHAR_BIT could be 32 and sizeof(long) could be 1.

We couldn't ship it that way. Customers wanted to run real-world source code and they wanted to employ normal software developers. We hacked up the compiler to rotate data addresses by 2 bits so that we could make CHAR_BIT equal to 8.

That was the 1990s, with an audience of embedded RTOS developers who were willing to put up with almost anything for performance. People are even less forgiving today. If strangely sized char couldn't be a viable product back in the 1990s, it has no chance today. It's dead. CHAR_BIT is 8 and will forever be so.

Re: Tell HN: C Experts Panel – Ask us anything about C

#799
post #126

I'm teaching C to high schoolers as their first language, which is quite the adventure. Do you have any good advice or resources on how to introduce the way C treats the function stack and heap allocated memory? Most of my students struggle (naturally) with making sense of function scoped identifiers and pass-by-value semantics.

I suggest The C Companion by Allen Holub for getting an idea of "behind the scenes".

For a more modern look, i suggest Computer Systems: A Programmer's Perspective by Bryant and O'Halloran

Of course, you would need to pick and adapt the content for your students.

Re: Tell HN: C Experts Panel – Ask us anything about C

#800

Earlier quoted context omitted.

Rather than trying to decide whether to require that all implementations must use two's-complement math, or suggest that all programs should support unusual formats, the Standard should recognize some categories of implementations with various recommended traits, and programs that are portable among such implementations, but also recognize categories of "unusual" implementations. Recognizing common behavioral charact…

This sounds like something memcpy would do already for you?

A 36-bit system with (it sounds like) 9-bit bytes stores bit 8 of a int in bit 8 of a char, and bit 9 of the int in bit 0 of the next char; memcpy won't change that. They're asking for somthing like:

  unsigned int x = in[0] + 512*in[1] + 512*512*in[2] + 512*512*512*in[3];
  /* aka x = *(int*)in */
  
  out[0] = x & 255; x>>=8;
  out[1] = x & 255; x>>=8;
  out[2] = x & 255; x>>=8;
  out[3] = x & 255;
  /* *not* aka *(int*)out = x */
Post reply on HN