Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Activity for alx‭

Type On... Excerpt Status Date
Comment Post #296669 @#8176 And there are more issues. If `restrict` were designed to enable safer code (which should be the goal), it would disallow pointing to an object from two different parameters. However, it is really an optimization-only feature (it's designed so that you can point from two parameters,...
(more)
about 22 hours ago
Comment Post #296669 > It sounds like they were indeed just talking nonsense then, not aware of the C17 clarification to _Generic. Either that, or maybe they're pedantic enough that they cared about pointers-to-pointers (which doesn't even work well for `restrict`...). > Although it would technically be possibl...
(more)
2 days ago
Comment Post #296669 Found. The comment seems to be this one: Member body / National Committee: `GB` Comment number: `112` Clause/subclause: `6.7.3` Paragraph: `9` Type of comment: `ed` (editorial) Comments: > The statement about removing restrict not changing behavior of a conforming program is...
(more)
2 days ago
Comment Post #296669 > Yeah sure you can do pointer-to-pointers or function pointers but was that really the meaning of 6.7.4? The new versions of the standard don't come with a rationale, so we're a bit blind about what they did and why. I've only joined the committee after C23, so I don't know details of discus...
(more)
2 days ago
Comment Post #296669 ```c char *restrict *p; _Static_assert(_Generic(p, char *restrict *: 1, char **: 0)); ``` ```sh $ gcc -Wall -Wextra -Wpedantic -S r.c $ ``` > Notably, pointed-at data cannot be restrict qualified, only the pointer object itself. Is there such a constraint in the language? I've n...
(more)
3 days ago
Comment Post #296595 ... And thus, this is not an appropriate example for discussing whether using an indeterminate value results in UB (potentially or definitely), because this example is not using an indeterminate value at all. Here I'm not arguing whether reading the indeterminate value results in UB or not....
(more)
8 days ago
Comment Post #296595 @#8176 Yes, I was wrong on the first comment and the title. That I admitted above. The reason why I'm insisting on lvalue conversion is this reasoning in your post: > Even more obvious: > > ```c > int* p = malloc(n); > free(p); > p = NULL; > ``` > > If using p while the value ...
(more)
8 days ago
Comment Post #296595 That is, "evaluation" isn't a black-or-white thing. It's not "everything happens" or "nothing happens". It's more like in general, evaluation means several things, but in some cases, only one or a few of these things actually happen. Also, the effects of evaluation on the expression might be d...
(more)
8 days ago
Comment Post #296595 For example, in `*(p+1) = 0`, the whole `*(p+1)` is an lvalue expression, and is evaluated for designating an object and for initiating the side effect of writing a `0` to it, but its stored value is not read (lvalue conversion is not performed on the whole). But `p` is a subexpression of it, ...
(more)
8 days ago
Comment Post #296595 @#8176 C23 5.1.2.4p2 indeed says that `Evaluation of an expression in general includes both value computations and initiation of side effects.`, but I think that `in general` is meant to be overridden by specific rules. Indeed, as you say, the left operand of `=` has to be evaluated for its...
(more)
8 days ago
Comment Post #296595 You're right: the left operand is evaluated. However, that evaluation is only performed for determining the designated object. The value stored in the designated object is not read; that would require lvalue conversion, which is inhibited for the left operand of the simple assignment operator (...
(more)
8 days ago
Comment Post #296588 @#119116 It's not any indeterminate values. Only pointer values cause this unconditional UB, as specified by 6.2.4p2. However, it's true that casting the value doesn't change 6.2.4p2, so yes, it's still UB.
(more)
11 days ago
Comment Post #296595 > Even more obvious: > > ```c > int* p = malloc(n); > free(p); > p = NULL; > ``` > > If using p while the value is indeterminate, you wouldn't even be able to write bog standard code like the above, because the assignment involves a value computation of the left operand p before it is w...
(more)
11 days ago
Comment Post #296587 @#8176 Thanks! Yeah, I was wrong in my first message. It's not so clearly UB; it could be, but it isn't necessarily.
(more)
22 days ago
Comment Post #296587 ... But the call above is reading it through an lvalue that is a pointer, and would produce UB if and only if it is a non-value representation (which we don't know).
(more)
22 days ago
Comment Post #296587 @#8176 Hmmm. Thanks! So, it indeed becomes an indeterminate representation, which means it either represents an unspecified value or is a non-value representation. If it's an unspecified value, reading it results in unspecified behavior (which means it can have any value, and if you rea...
(more)
22 days ago
Comment Post #296587 Yes, it is. To be specific, the following program triggers UB: ```c #include <stdio.h> #include <stdlib.h> int main(void) { int *p = malloc(42); free(p); printf("%p\n", p); // UB; use-after-free } ``` Even though it doesn't access memory through the pointer.
(more)
26 days ago
Comment Post #282566 @#8176 I've been thinking about how an ideal fgets(3)-like API would look like, and I've developed an API that I think I like slightly more than fgets(3). ```c // fgettextline - FILE get text line char * fgettextline(char *buf, size_t n, FILE *stream) { if (n > INT_MAX) { errno = E...
(more)
30 days ago
Comment Post #282566 @#8176 And I forgot to mention the obvious: POSIX also requires that all lines are terminated by '\n'. If a line doesn't contain that '\n', it's invalid. And also forgot to mention: stpsep() does two things: it validates the line, and it removes the '\n'. Both at the same time.
(more)
about 1 month ago
Comment Post #282566 POSIX defines text files (that includes streams) as being composed of 0 or more lines. And lines are defined to not contain null bytes and be no longer than LINE_MAX characters (including the '\n', but not the '\0' of the string in which it is stored). If a stream contains null bytes, or does...
(more)
about 1 month ago
Comment Post #282566 @#8176 If I understand correctly, you mean when reading files that are not text files. Of course, fgets(3) is not good for reading non-text files. But that's not because fgets(3) is a bad API, but because it's not suitable for non-text files. There are APIs for non-text files. For text f...
(more)
about 1 month ago
Comment Post #296362 After a lot of research and discussing with other expert programmers, we found that the original use case of memccpy(3) was for implementing fgets(3). Indeed, it's perfect for that. After all, it's not a bad function per se. Like strncpy(3), it's good for a niche use case. But it's certai...
(more)
about 2 months ago
Edit Post #296362 Post edited:
V7 had bcopy(), not bcmp(3). Also, SysV had <memory.h>.
about 2 months ago
Edit Post #296362 Post edited:
truncation is also dangerous, in a different way
about 2 months ago
Edit Post #296384 Post edited:
tfix
2 months ago
Edit Post #296384 Post edited:
tfix
2 months ago
Edit Post #296384 Post edited:
pfix
2 months ago
Comment Post #282566 Why would you want to know how much it read? If you really want to know, it should be as simple as `strlen(buf)`, which yeah, might be a bit inefficient, but compared to reading a file, is that observable? Or does it have any obscure/dangerous/tricky behavior? What do/would you use instead?
(more)
2 months ago
Comment Post #282566 I never understood why scanf(3) is taught to new programmers. fgets(3) is way simpler, and easier to use. And scanf(3) is in general avoided outside of teaching, so it would be better to avoid it entirely. fgets(3) also helps programmers think of text files, which is usually a good format. ...
(more)
2 months ago
Edit Post #296384 Initial revision 2 months ago
Answer A: Extern keyword in C and proper way to use extern variables in embedded systems
> And with the same logic, shouldn't the function prototypes in gpio.h also be extern for my source files to see them? Function declarations default to being `extern`. If you don't specify any storage-class specifiers, a function prototype is `extern`. This is specified in C23 in 6.2.2p5: ...
(more)
2 months ago
Comment Post #296363 Although, if you want to chain, the stpecpy() interface is superior.
(more)
2 months ago
Comment Post #296363 > As for comparing memccpy with functions that don't take a buffer size as parameter, that's comparing apples and oranges. If you don't use the buffer size, then you can't use the function for stuff like input sanitation, which would be a possible use-case for memccpy. Unlike all of the str... fu...
(more)
2 months ago
Comment Post #296363 > If we want to know if the whole source string was copied or not, we can do this: And then you show an example: ```c const char* expected_end = s2 + sizeof(s1); char* result = memccpy(s2, s1, '\0', sizeof(s2)); ... if(result == expected_end) { ... } ``` I believe that code has UB,...
(more)
2 months ago
Comment Post #296363 I think it would be okay to define a function that copies a string only if it fits, and which returns a pointer to the NUL if it fits. That function could be indeed implemented with memccpy(3), hiding its ugly and dangerous interface: ``` char * stpcpy_if_fits(size_t dsize; char dst[re...
(more)
2 months ago
Comment Post #296363 > If you do use it for strings, I find the usage rather straight-forward: And you show this example: ```c #include <string.h> #include <stdio.h> int main(void) { char s1[] = "hello world"; char s2[100]; char* result = memccpy(s2, s1, '\0', sizeof(s2)); if(result == NULL)...
(more)
2 months ago
Comment Post #296363 A function that returned a pointer to the NUL character of the string could be used as this: ```c while (NULL != (nul = fgetsnul(buf, countof(buf), stdin))) { if (streq(buf, "") || nul[-1] != '\n') goto invalid_line; strcpy(--nul, ""); ... } ``` This is slightly...
(more)
2 months ago
Comment Post #296363 > functions that come with a broken API, for example fgets Currently, fgets(3) can be used usually as this: ```c while (fgets(buf, countof(buf), stdin) != NULL) { if (stpsep(buf, "\n") == NULL) // Remove '\n' if present goto invalid_line; ... } ``` (where stpsep(...
(more)
2 months ago
Comment Post #296363 > we do get a pointer to where it stopped copying, so we can calculate the size copied. Which really ought to be "minimum viable product" for any function that writes/copies memccpy(3) is not such a minimum viable product. The minimum viable product for a function that copies bytes and return...
(more)
2 months ago
Edit Post #296362 Post edited:
Linux has strscpy(9), but no strscat()
2 months ago
Edit Post #296362 Post edited:
strecpy(2) is not buggy; seprint(2) is
2 months ago
Edit Post #296362 Post edited:
tfix s/strcpy/strncpy/
2 months ago
Edit Post #296362 Initial revision 2 months ago
Answer A: Are memccpy(3) or strncpy(3) bad for copying and catenating strings with truncation?
strncpy(3) strncpy(3) was originally invented in Seventh Edition Unix (a.k.a., V7). It was added with one use case in mind: copying a source string into a destination character sequence in a fixed-size buffer (not a string), and padding the unused bytes with `'\0'`. This was useful back th...
(more)
2 months ago
Edit Post #296361 Post edited:
2 months ago
Edit Post #296361 Initial revision 2 months ago
Question Are memccpy(3) or strncpy(3) bad for copying and catenating strings with truncation?
I heard strncpy(3) is bad, and also heard that C23 added memccpy(3) to replace it. However, I also heard memccpy(3) is even more terrible than strncpy(3). Are these functions really bad? How so? Are there any legitimate uses of any of these functions? What should we use instead?
(more)
2 months ago
Comment Post #296352 If one prefers the simplicity of strcpy(3)/strcat(3), one can also have such functions. They are less efficient, but they can be safer, by being even simpler to use in some cases. I have truncating variants of these functions, which I call strtcpy()/strtcat(). They'd be used as: ```c if (s...
(more)
2 months ago
Comment Post #296352 ... At the bottom of the paper n2349 there's a more correct example of how memccpy(3) could be used to copy strings. This shows how terrible this function is. ```c char *p = memccpy (d, s1, '\0', dsize); if (p) { --p; p = memccpy (p, "/", '\0', dsize - (p - d)); if (p) { --...
(more)
2 months ago
Comment Post #296352 ... But now about the flagship use case: copying with truncation. It shows that one should do this: ```c char *p = memccpy (d, s1, '\0', dsize); dsize -= (p - d - 1); memccpy (p - 1, s2, '\0', dsize); ``` This is more prone to off-by-one bugs than the case above, and more than strnc...
(more)
2 months ago