Print UTF-32 string with wprintf - c11

I am migrating some code from using wchar_t to char32_t, and when compiling with the -Werror=pointer-sign flag set, I am getting the following issue:
// main.c
#include <uchar.h>
#include <wchar.h>
int main(void) {
wprintf(U"some data\n");
}
Compiling: gcc -std=c11 -Werror=pointer-sign main.c
Output:
main.c: In function ‘main’:
main.c:5:10: error: pointer targets in passing argument 1 of ‘wprintf’ differ in signedness [-Werror=pointer-sign]
wprintf(U"some data\n");
^~~~~~~~~~~~~~
In file included from main.c:2:
/usr/include/wchar.h:587:12: note: expected ‘const wchar_t * restrict’ {aka ‘const int * restrict’} but argument is of type ‘unsigned int *’
extern int wprintf (const wchar_t *__restrict __format, ...)
^~~~~~~
To remedy this, I can do:
wprintf((const int *)U"some data\n");
//or
printf("%ls\n", U"some data");
Although this is quite a pain. Is there a nice and easy way to do this? What is the real difference between const unsigned int* vs const signed int*, aside from the data type it points to? Is this possibly dangerous, or should I just disable the flag altogether?

char32_t is an unsigned type.
wchar_t is either signed or unsigned, depending on implementation. In your case, it is signed.
You can't pass a pointer-to-unsigned where a pointer-to-signed is expected. So yes, you need a type-cast, however you should be casting to const wchar_t *, since that is what wprintf() actually expects (wchar_t just happens to be implemented as an int on your compiler, but don't cast to that directly):
wprintf((const wchar_t *)U"some data\n");
It doesn't get much cleaner than that, unless you wrap it in your own function, eg:
int wprintf32(const char32_t *str, ...)
{
va_list args;
va_start(args, str);
int result = vwprintf((const wchar_t *)str, args);
va_end(args);
return result;
}
wprintf32(U"some data\n");
Note that this code will not work properly at all on platforms where sizeof(wchar_t) < sizeof(char32_t), such as Windows. On those platforms, where sizeof(wchar_t) is 2, you will have to actually convert your string data from UTF-32 to UTF-16 instead, eg:
int wprintf32(const char32_t *str, ...)
{
va_list args;
int result;
va_start(args, str);
if (sizeof(wchar_t) < sizeof(char32_t))
{
wchar_t *str = convert_to_utf16(str); // <-- for you to implement
result = vwprintf(str, args);
free(str);
}
else
result = vwprintf((const wchar_t *)str, args);
va_end(args);
return result;
}
wprintf32(U"some data\n");

Related

passing command line argument value to a string

#include <bits/stdc++.h>
using namespace std;
int main(int argc,char* argv[]){
string str = atoi[1];
cout<< str;
}
I get an error in this, is there any solution, so that when I get input from the command line argument and store that in str, and use for the operation

Compilation error on blocks with return type

I have the following block code
typedef BOOL(^FieldValidationBlock)(NSString *);
FieldValidationBlock aBlock = ^(NSString *input){
return ([input length] == 10) ;
};
which throws me a compilation error thats tates the return type is int and should be BOOL.
when I add a cast it works just fine:
typedef BOOL(^FieldValidationBlock)(NSString *);
FieldValidationBlock aBlock = ^(NSString *input){
return (BOOL)([input length] == 10) ;
};
why this happen?
Because BOOL is an objective C type, and the logical comparison operators are standard C. In standard C the return type of comparison operators is an int. This is important to know sometimes, as when you negate a value that you assume to be boolean, but is in fact an int, it's not necessarily going to be what you expect.
In your example, casting to a BOOL is fine.

How to use Array of C language with Objective-C

I'm using Objective-C language. But I don't know how to use c with Objective-C.
Ex) This is Function method.
- ( ?? ) function{
unsigned int first = ..
unsigned int second = ..
unsigned int third = ..
int infoData = {first,second,third};
return infoData;
}
How to fill in parenthesis.
I don't use NSArray.
Please help me.
the answer is the same as it is in C. Objective-C is a strict superset of C.
Assuming you declared int[] infoData you could make the return int*, but you're still going to have problems because the array is allocated on the function's stack. You'll need to dynamically allocate space for it just like you would in C.
(You cannot use int[] as a return type)
The code below will compile, but gcc will warn about returning the address of a function local variable.
#interface test
- (int*) function;
#end
#implementation test
- (int*) function{
unsigned int first = 0;
unsigned int second = 1;
unsigned int third = 2;
int infoData[] = {first,second,third};
return infoData;
}
#end

Convert unsigned char * to int * in Objective-C

I am trying to convert a unsigned char* to int * on in Objective-C on the iPhone. Is there any API that can help with the conversion?
Here's my best attempt:
-(BOOL)MyFunc:Version:(int *)nVer
{
unsigned char * uszVerSize;
//trying to assign string to int
nVer = uszVerSize[0] ;
}
Dear Lord, I think you have bigger problems than the one stated above.
You need to convert the chars to an int and return that.
return [[NSNumber numberWithUnsignedChar:uszVerSize] intValue];
You should also learn about pointers and how ints and chars differ in memory. You can't just assign a pointer to a char to a pointer to an int.
const char *asciiCString = [#"abc-zABC-Z" cString];
int cStringLen = [#"abc-zABC-Z" length];
for(i=0;i<cStringLen;i++) {
[asciiMArray addObject: [[NSNumber alloc] initWithInteger: asciiCString[i]]];
printf("%d\n",asciiCString[i]);
}
for(i=0;i<cStringLen;i++) {
NSLog(#"%#",[asciiMArray objectAtIndex: i]);
printf("%d\n",asciiCString[i]);
}
This is a code i wrote yesterday, to test some code of my learning face
It may look naive...but if it helps you....
asciiCString[i] returns you ASCII value of the char referenced at the index..
asciiMArray is a NSMutableArray Object

Proper checking of nil sqlite text column

I have an sqlite string column that is assigned to a string. I need to make sure it isn't nil before assigning. I'm doing this:
char *isNil = sqlite3_column_text(selectstmt, 2);
if(isNil != nil){
myName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)];}
which gives the warning:
warning: initialization discards qualifiers from pointer target type
What is the proper way to do it?
You're getting the warning as you're ignoring the const. The API is defined:
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
You're assigning the return to a char*, so you're dropping the const. That is why you get the warning. You should respect the const.
const unsigned char *isNil = ...
I'm not really a huge objective-c guy, but I think stylistically it's common practice to compare primative types against NULL rather than nil. Also there is no need to call column_text twice.
const char *columnText = (const char *)sqlite3_column_text(selectstmt, 2);
if(columnText != NULL)
{
myName = [NSString stringWithUTF8String: columnText ];
}
You can see above I've cast the const unsigned char pointer to a const signed char pointer. You should make sure you know when you cast away a warning that it is the right thing to do. In this case it is safe to cast to an signed char. In general, never cast away const though, as whoever made that API could be doing something that requires you to treat the data as const.