Hot answers tagged

53

The C standard of the language doesn't mandate a 32 bit int. It defines sizeof(char) == 1 per definition and sizeof(long long) >= sizeof(long) >= sizeof(int) >= sizeof(short) >= sizeof(char) It also mandates that the constant in limits.h are at least the values given below #define CHAR_BIT 8 #define CHAR_MAX UCHAR_MAX or SCHAR_MAX #define ...


37

This is (or at least appears to be) the binary euclidean GCD. https://en.wikipedia.org/wiki/Binary_GCD_algorithm has a slighty different version (but the version you post has the nice feature that there's no recursion (which I seem to recall earlier C compilers wanted to limit). As I noted in my comment that I deleted when I realized I do have access to ...


34

In V6, the C preprocessor is part of cc, the compiler driver; see the expand() function in cc.c. The directory you linked to contains the source code to the two passes of the C compiler, c0 and c1 (and their floating-point variants, fc0 and fc1), and the optional optimiser, c2. The passes are driven by cc, whose source code is available in the s1 directory. ...


19

The reason is that it's quicker. You just need to look up GCD in Knuth, that is Volume 2 of TAOCP, to get answers and analysis. There you have comparisons of "Original Euclidean algorithm", "Modern Euclidean algorithm" and "Binary gcd algorithm". The last one is introduced with the remark that "Since Euclid's patriarchal ...


18

There is no such requirement in standard C. Traditionally, an int was required to be at least 16 bits, though since the mid-1980s I started to write code as if an int was at least 32 bits, confident I did not intend to support older hardware. When we moved to 64-bit systems, it was common in some implementations for int to remain at 32 bits, since this eased ...


14

If you need a date, then March 12, 1997. That's when Single UNIX Specification version 2 (aka UNIX98) was released. Among other changes to the ISO C standard (via limits.h), INT_MAX and INT_MIN were changed to 2,147,483,647 and -2,147,483,647, respectively (the same as LONG_MAX and LONG_MIN). This of course does not mandate a 32-bit int (64-bit ints are ...


14

The keyword was inherited from B. B was a programming language with no type system at all: every variable held a machine word (corresponding to the int type in C), and the type of each value was determined by the operation performed. Since there was no type to specify for variables, the only thing to declare about a variable was its storage class; unlike in ...


13

The point of fread/fwrite is to write N elements, each of size S bytes. The API is not a simple 'write this number of bytes' interface. Thus, for example: struct S { int a, b; float c; }; struct S stuff[92]; fwrite(stuff, sizeof (struct S), 92, stream); (I would not write '92' in real code, but I want the simple formulation in this example) Thus it has two ...


12

These are OMF libraries; you can analyse them with Agner Fog’s object file converter. It probably only makes sense to work with those libraries if you intend to build software with Microsoft C 5.1, in which case you’d use the tools provided with the compiler (LIB.EXE in particular). The OMF format is described in detail in OMF: Relocatable Object Module ...


12

Since the inline assembler of cc65 doesn't accept anonymous labels (from my other answer), another approach is to provide a unique suffix to the labels, which can be applied by the macro. The stringizing operator of the C preprocessor, and the fact that C string literals written consecutively are automatically concatenated, might make this more convenient: #...


11

If I was to write an Amiga game, what would be the best/most reliable way to detect how much RAM is actually available? The routine you're quoting is only able to detect chip memory (not fast memory), by hardware banging in certain areas. Games sometimes tried $C00000 (popular slow memory location) in the same fashion. But there are too many fast memory ...


11

As others have said, this is Stein's algorithm, and is remarkable for having taken so long to be discovered, considering the importance of GCD to number theory. While it was discovered at least as early as 1962, it was not published until 1967. One thing that hasn't been mentioned is that it scales much better than division. As you deal with larger and ...


10

2.9BSD, being a self-hosting operating system, includes all the source code and all the tools necessary to build it. That includes the C compiler, the assembler, and everything. There is no mention anywhere of any of this being renamed for DEMOS, so it's a safe bet that they had the same name. DEMOS is similar in spirit to something like Russian Fedora Remix,...


9

You’re correct, the goal of this code is to ensure that the allocated buffer is entirely contained within the same DMA segment (DMA operates on 64KiB segments, not to be confused with the 16-byte-aligned real-mode segments of the x86 addressing model). The assumption that the allocator returns successive blocks is safe, at least before the heap gets ...


9

The book "Writing Solid Code" documents an instance where the size of an int changed. There is a section which noted that (once upon a time) Microsoft's own internal C code sources often hard-coded the value '2' (bytes) instead of writing 'sizeof(int)', under the theory that "... well, we OWN the C compiler -surely our own compiler group ...


8

I do wonder though if that's a good way to work across all Amigas, from an original A1000 with 256k Chip RAM to an A4000 with 2MB Chip and 4MB Fast RAM. No, it's a very bad way. This code can only be safely used if you have killed the OS and taken over completely - then you have to be aware of all possible differences between machines, including additional ...


8

The NetHack sources have several macros which are conditional on whether KR1ED is defined, which stands for Kernighan and Ritchie's book The C Programming Language first edition. If one's compiler is pre-ANSI, you must #define KR1ED; if your compiler is ANSI-compliant, you leave KR1ED undefined. Thus, the change in how functions are prototyped occurred ...


7

void xms_move_xmb_internal(unsigned int ds, unsigned int si) { _AX = 0x0B00; _DS = ds; _SI = si; (*xms_driver.function_ptr)(); } looks like a bad idea. The compiler assumes DS to point to the global data segment of your program. In the large memory model, the stack segment can differ (I don't remember the default) from the data segment. ...


7

AT&T's documentation for fread and fwrite that pre-dates size_t is quoted below. But first, to answer the title question: Both functions are designed for objects, not characters. This is evidenced by the return value being a count of the objects read or written, not the number of characters. Each function may read/write fewer objects than requested. ...


7

It avoids recursion, so the resources required (in particular stack depth) are independent of the parameters. OP might find that the book didn't assume the availability of virtual memory, or targeted CP/M or real-mode x86 systems with a stack limit of 64K. How does Knuth deal with this in his 1970s books?


6

What should be emphasized more because it is perhaps unexpected is that the C standard and POSIX differ in their requirements for the value range of an int. Specifically and importantly, C never mandated 32 bit int sizes. The reason for the discrepancy may be in the different assumptions each standard can make about the hardware. C is used for a wide variety ...


6

When C was invented, there was no particular reason why an implementation would want to use a value for int which was smaller than a register. Although the Standard allowed implementations to choose almost any means they wanted to pick the sizes of integer types, the common practice was that, absent any reason to do otherwise: char would be the smallest ...


6

So bare metal, no OS? On both systems, console terminal I/O is considerably easier than any other terminal interface. On many VAXen, there's a couple of processor registers that are status and data registers for console I/O. Much easier than dealing with DZ-11 or similar. Here's the important part of a VAX 'putchar' routine from a standalone libc I wrote in ...


6

Compilers targeting DOS typically provide macros to manipulate the segment and offset of far pointers. FP_SEG(pointer) provides access to the segment portion, FP_OFF(pointer) to the offset. It's also possible that there's a MK_FP(segment, offset) or FP_CONSTRUCT(segment, offset) macro to combine segment and offset into a pointer. This discussion in comp.os....


5

It's not really clear in what context the question is asked, so I'll try to go along. Should C be regarded as an intermediate language on a virtual machine named PDP-11 Architecture (which have a plain memory space and stacks), like opcode to jvm, msil to dotnet, asm.js to v8, which has to be translated and optimized for real machines of different ...


5

The problem is that you're trying to access the function parameter data, but the compiler does not expose that as a symbol to the internal assembler, so it's looking in the public, global namespace for it -- and can't find it. According to SDCC - Interfacing with Z80 assembler code, you do indeed need to access the parameters from the stack. I don't know if ...


5

I don't know about a standard, but Microsoft chose the LLP64 model for 64-bit Windows, which means that everything except pointers stays as if the processor word size were 32-bit. Raymond Chen's blog, The Old New Thing, has an explanation for why they made that choice (which builds on a now-dead link to this MSDN page). (In short, to make 64-bit porting ...


5

Minority report: user3840170 answered: I’d assume auto was never popular in C in the first place, as int is one character shorter, so everyone declared the type anyway. Some of us more anal retentive types always used "auto": auto int x; auto int y; as two lines, never as: int x, y; It made it much easier to find all the declarations by simply ...


Only top voted, non community-wiki answers of a minimum length are eligible