0

Here is an example for what I mean:

int open(const char *pathname, int flags);

and from the man page. Looking into Linux, it is obvious the flags are bit markers.

I am curious by the use of an int as a way to set specific bits, as I had thought that the most "portable" and recommended way to do this is to use an unsigned int of specific size, perhaps uint32_t.

Does anyone have any insight as to why this is? This is a purely educational question and I am asking out of curiosity.

user129393192
  • 797
  • 1
  • 8
  • 1
    Probably a legacy thing. – Eugene Sh. Jun 15 '23 at 19:21
  • 3
    This API predates C89, so, yes, it's a legacy thing. (I'm not making this an answer because I can't back that up with historical evidence.) – zwol Jun 15 '23 at 19:22
  • Is it unsafe or unportable practice in any way? In a university assignment related to bit twiddling, we also used `int` types for all of it and simply assumed they would be 32-bits. – user129393192 Jun 15 '23 at 19:23
  • If the bitfields are examined with masks, it shouldn't make any difference whether the enclosing type is signed: only that it is big enough. – Weather Vane Jun 15 '23 at 19:29
  • 1
    The problem bitwise operations with signed integers are shifts, because of what happens with the sign bit. Masking works the same as with unsigned. – Barmar Jun 15 '23 at 19:31
  • Could you have an issue where signed overflow is undefined behavior, even if only messing with the bits, but you used an `int` and `<<`? – user129393192 Jun 15 '23 at 19:33
  • Yes, but the right-shift is the problematical one. It would be unlikely in this function implementation, which might use, say, `if((flags & O_RDONLY) != 0)` – Weather Vane Jun 15 '23 at 19:41
  • I see. I was asking for my own use. I would think left-shift is problematic (put bits onto the MSb). Why do you say right? From my understanding, it is an arithmetic shift. – user129393192 Jun 15 '23 at 20:37
  • For what purpose are you shifting bits? Related: [Are the shift operators (<<, >>) arithmetic or logical in C?](https://stackoverflow.com/questions/7622/are-the-shift-operators-arithmetic-or-logical-in-c) – Weather Vane Jun 15 '23 at 21:04
  • Consider for example a function that extracts the MSb of an integer @WeatherVane. It would require shifts. I’m wondering if that’s UB, and why you are saying it would be problematic for right shift — which is arithmetic for `int` (I see left shift causing overflow). – user129393192 Jun 15 '23 at 21:30
  • It does not require a right shift, only a mask to extract a specific bit. `O_RDONLY` doesn't specify a bit number for a shift: just a bit mask. The `int` variable here is not performing the role of an *integer*. It's just a set of bits. If you want to extact the MSB it's `(flag & 0x80000000)` for a 32-bit `int`. – Weather Vane Jun 15 '23 at 22:29
  • Sorry, the MSb that is set. That would require right shift, and I am asking about in general, what cases are considered UB. Not sure why you continue to get around what I am asking. Three comments ago I specifically ask why right shift is UB. I see left shift being UB (set MSb or go past MSb) but not right shift. – user129393192 Jun 15 '23 at 22:32
  • Please read the comments - **no shift is needed**. Are you trying to extend the question to something different? – Weather Vane Jun 15 '23 at 22:32
  • I am not asking if it is needed or not. You simply stated right shift is UB. I looked into it and it is implementation-defined. I wanted to hear your reasoning. And yes, it would be needed to extract the MSb that is SET (i.e, the top 1 bit) – user129393192 Jun 15 '23 at 22:34
  • I keep repeating myself. The top bit is `(flag & 0x80000000)` and no shift is needed. – Weather Vane Jun 15 '23 at 22:35
  • And I also keep repeating. You are writing a code to extract the top bit. I gave an example that would need a right shift (extracting just the most significant bit that is set — this is a different thing) and asked why you say right shift is UB. – user129393192 Jun 15 '23 at 22:37
  • For example, 0101, extracting would result in 0100. That is what I mean. And I am simply asking why you say right shift is UB. – user129393192 Jun 15 '23 at 22:37
  • @WeatherVane *`O_RDONLY` doesn't specify a bit number for a shift: just a bit mask* [`O_RDONLY` is not a bit mask](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/open.html): "In historical implementations the value of O_RDONLY is zero. Because of that, it is not possible to detect the presence of O_RDONLY and another option." Neither are `O_WRONLY` and `O_RDWR`: "Applications shall specify exactly one of the first five values (file access modes) below in the value of `oflag`..." – Andrew Henle Jun 16 '23 at 17:20
  • @AndrewHenle but do they need shifting? I admit I picked the wrong example with `O_RDONLY` which would appear to be the default when no other modes are specified. More generally, sometimes combinations of flags are used for a particular macro, but they are still masks. – Weather Vane Jun 16 '23 at 17:40

1 Answers1

1

If I remember correctly from Unix V7, there were only 3 values allowed for the open() flags: 0 (read) 1 (write) and 2 (read-write). So, at that time, this was not a "flag" but a "mode" taking an enumeration of 0, 1, 2 : hence the "int" type.

If these where really flags, logically O_RDONLY could not be 0 and O_RDWR should be equal to O_RDONLY|O_WRONLY, which is not the case.

Later, when other flags were added, the type was kept "int" to avoid breaking the compilation of existing code when using severe control of the warnings.

J.P. Tosoni
  • 549
  • 5
  • 15
  • `O_RDONLY`, `O_WRONLY`, and `O_RDWR` are [definitively **not** bit flags](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/open.html): "In historical implementations the value of `O_RDONLY` is zero. Because of that, it is not possible to detect the presence of `O_RDONLY` and another option. ..." – Andrew Henle Jun 16 '23 at 17:22
  • Interesting. This means that you never really have to specify `O_RDONLY`, if you rely on the implementation @AndrewHenle – user129393192 Jun 20 '23 at 19:23
  • You can also specify `O_RDONLY` and another file opening option. – user129393192 Jun 20 '23 at 19:23