Comments (4)
Merged!
I renamed param 'user' to 'arg' for more common nomenclature.
from printf.
Hi guys! I have an additional question (suggestion) regarding @sgoll's merge.
The starting reason why I came to this is that on ARM GCC with -Wcast-align
(which is one of the additional warnings parameters we use with ARM to avoid alignment issues) we get an alignment warning when casting the char*
to a struct pointer in this function:
static inline void _out_fct(char character, char* buffer, size_t idx, size_t maxlen)
{
// warning: cast from char* to out_fct_wrap_type* increases
// required alignment of target type
((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg);
}
Although it isn't the case here (buffer
always points to an actual struct
instance when this function is called), the warning would generally make sense according to the C standard (6.3.2.3 ยง7):
If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.
So the cast itself is not undefined behavior, unless the pointer is misaligned at runtime, which it isn't.
But anyway, at first I thought of using a #pragma
to disable the warning, but then I also noticed that (as of this revision) the buffer
parameter is actually a "special case", used only inside _out_buffer
and it seems like there is no need to use it everywhere.
That is, writing to char* buffer
is actually just a special case of the function call where the newly introduced void* arg
would point to char* buffer
, and the _out_buffer
function would just cast it to char*
, while _out_char
would again simply ignore the arg
part completely.
To clarify, this would require replacing the char*
pointer with void*
:
// char* buffer becomes void* arg, because this will work the same way for fctprintf
typedef void (*out_fct_type)(char character, void* arg, size_t idx, size_t maxlen);
// out_fct_wrap_type takes this same signature
typedef struct {
out_fct_type fct;
void* arg;
} out_fct_wrap_type;
And then all calls to out(...)
would be changed from
static int _vsnprintf(out_fct_type out, char* buffer, ...
{
...
out(character, buffer, idx++, maxlen);
...
}
to
// no need to pass `out_fct_type` and `char*` separately to this function,
// because `out_fct_wrap_type` wraps them both
static int _vsnprintf(out_fct_wrap_type out, ...
{
...
out.fct(character, out.arg, idx++, maxlen);
...
}
And then individual "overloads" of printf
would change from:
int printf(const char* format, ...)
{
...
char buffer[1];
const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
...
}
to something like this:
int printf(const char* format, ...)
{
...
const out_fct_wrap_type out_fct_wrap = { _out_char, NULL };
const int ret = _vsnprintf(out_fct_wrap, (size_t)-1, format, va);
...
}
Does this make sense? There would be no changes to the public interface, except the func signature in fctprintf
(which perhaps isn't a bad thing because it lets the caller get the idx
too).
Sorry for potential typos. If you are interested and don't think that this will change the code too much (shouldn't change the public interface though), I can make a PR.
Thanks!
from printf.
You are absolutely right! I'm a big fan of void* arguments passed to callback functions.
In the case above, I just thought it won't be necessary, but your example is a use case.
So, I merge your PR shortly. THANKS!
from printf.
Hello Vedran, thanks A LOT for your detailed description and bringing -Wcast-align
to attention.
You got a point here, obviously the char* pointer is always correct aligned when pointing to the wrapper struct, but I agree, it's not 100% clean regarding the standard.
Suppressing warnings may help in certain situations but is not the intention here, because this module should work rocksolid in any environment.
I think, you are right, replacing the char*
pointer by a void*
might solve the problem. Going to investigate this...
from printf.
Related Issues (20)
- Use more appropriate types for base, precision and width HOT 4
- Avoid geneal-case division and modulus in _ntoa functions
- Undefined behavior on INT_MIN HOT 1
- Proper handling of denormals
- printf_("%.1e", 9.96) prints "10.0e+00", should print "1.0e+01"
- Printing +/-0 with "%g" doesn't fall back to decimal mode
- More cases of "%g" not falling back to decimal mode
- Support for FreeRTOS lxip specifier HOT 1
- Siginificant-digits-to-precision transition made invalid by rounding
- Floating point printing - how?
- Vfctprintf
- could you support %I64d %I64u like msvc done? HOT 1
- [notice] https://github.com/eyalroz/printf <-This repo is maintaining HOT 8
- Zero padding disabled when precision specified HOT 3
- this is incredible HOT 6
- WebAssembly HOT 2
- GCC flags for freestanding? HOT 2
- for declaration not compatible with C compilers HOT 1
- _vsnprintf reads past the format parameter value HOT 6
- I've created an Arduino Library from your source code HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from printf.