473,757 Members | 2,284 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

The void** pointer breaking symmetry?

Hi Clers,

If I look at my ~200000 lines of C code programmed over the past 15
years, there is one annoying thing in this smart language, which
somehow reduces the 'beauty' of the source code ;-):

char *cp;
void *vp;
void **vpp;

// 1
cp=vp;

// 2
cp=*vpp;

Why is the first instruction allowed while the second one creates a
compiler warning/error?
If vpp is a pointer to a void pointer, why am I not allowed to assign
the content of vpp to a char pointer without ugly explicit casts? Why
is it needed to break the symmetry? Are there any GCC compiler options
to specifically disable this warning which doesn't make sense to me?

Thanks for your feedback,
Elmar

P.S.: In case this is an old question: Googles inability to search for
'void**' made it hard to find the answer ;-)

May 5 '06
49 2802
Eric Sosman <es*****@acm-dot-org.invalid> writes:
el***@cmbi.ru.n l wrote:

[...]
Typical example: the function mem_freesetnull which frees a pointer and
sets it to NULL (very helpful in the context of exception handling):
Ideally, it would take the address of a pointer as argument and look
like that:
void mem_freesetnull (void **ptradd)
{ mem_free(*ptrad d);
*ptradd=NULL; }
Unfortunately, that's not possible, because I'd have to use an ugly
explicit cast to (void**) in every call to the function.


Even the cast will not save you. Just as numbers come in
different flavors, pointers come in different flavors. Just as
you cannot set a number to zero without knowing its type, you
cannot set a pointer to NULL without knowing its type.


And even though many actual implementations implement all pointer
types the same way, the standard is carefully designed to allow
different pointer types to have different representations . For
example, on a system that only has word pointers in hardware, a char*
or void* (pointing to a subset of a word) might need extra bits to
indicate an offset within the word.

Conversion between void* and int* can be done because the compiler
knows how to convert from one representation to another. (The fact
that the conversion can be done implicitly isn't really relevant here;
it's just a convenience.) Conversion between void** and int** can
work only if void* and int* have the same representation, something
that's commonly true but is not guaranteed by the language.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 6 '06 #11
> > In my humble view, the ideal solution would be:
> 1) void* is a generic pointer type that can be implicitly converted
> to/from any other object that can be dereferenced at least !once!
> (e.g. char*, int*, also char**, int**, but not char,int)
> 2) void** is a generic pointer type [...]
No; stop right there. void** is not at "generic" at all,
not in the least. A void** is a pointer to a void*, and not
a pointer to any other kind of object or function.

Your confusion, perhaps, is this: A void* can point to any
kind of object, and can be converted to and from other object
pointer types without a cast. That's why it's often called
"generic," but the term is really very loose. However, a void*
is itself an object type, a perfectly concrete "real" object
type like an int or a char* or whatever. Just as with other
concrete object types, it's possible to form a pointer to objects
of this void* type. But such a pointer is in no way "generic;"
it can only be NULL or point to an actual void* object somewhere.


I am not sure about my level of confusion, I mainly encountered a
language feature that didn't 'feel' right (=efficient), so I asked
for the reason. Now I know that it's caused by exotic architectures
where pointers are not all guaranteed to have the same size, and
that the language pays the price of not being able to use a pointer
to any pointer as a function argument in one shot. You manually have
to cast your pointer to void* and back before and after the function,
requiring 3 lines instead of 1 line code. Thanks also for the other
similar answers from Keith Thompson and Michael Mair.
> [...] having identified the main cause of entropy (and also

> crashes ;-) in my current sources: The inability to safely pass a
> pointer to any pointer as a function argument.


That's right. C does not require that all pointers "smell
the same." Pointers to different types can come in different
shapes and sizes, so there's really no such thing as a "generic
pointer" (despite the common sloppy usage of the phrase to
describe void*). You might as well speak of a "generic number;"
just as short and double can look different, short* and double*
can look different.
> Typical example: the function mem_freesetnull which frees a pointer and
> sets it to NULL (very helpful in the context of exception handling):
> Ideally, it would take the address of a pointer as argument and look
> like that:

> void mem_freesetnull (void **ptradd)
> { mem_free(*ptrad d);
> *ptradd=NULL; }

> Unfortunately, that's not possible, because I'd have to use an ugly
> explicit cast to (void**) in every call to the function.


Even the cast will not save you. Just as numbers come in
different flavors, pointers come in different flavors. Just as
you cannot set a number to zero without knowing its type, you
cannot set a pointer to NULL without knowing its type.
> So in practice, I have to move the explicit cast to the function
> itself:

> void mem_freesetnull (void *ptradd)
> { mem_free(*(void **)ptradd);
> *(void**)ptradd =NULL; }

> Now the function looks ugly, but more importantly, I lost an important
> piece of type-safety:


Most important of all, the function is now incorrect.
You seem upset by all the warnings the compilers emit for
constructs of this sort, but it turns out they know C better
than you do: This code is wrong, and the compiler is right
to complain about it.
> I'm thinking about a GCC patch for an option to specifically disable
> the warning in the cases outlined above. But if that has zero chance of
> acceptance, I'll save my time ;-)


While you're at it, disable the diagnostics for unbalanced
parentheses, for `("Hello" / "world!")', and for all the other
programming errors that might be made. The source for gcc is
readily available; you are free to make changes and use your own
version if you choose -- but allow me to suggest that your choice
is ill-informed. In short, you don't know what you're doing; you
don't know C well enough.


I agree that mentioning a GCC patch was a bit provocative, sorry that I
hurt
your feelings. Nevertheless your comment and the emphasis you put on it
nicely illustrates that there are two types of programming brains:

#define FOOS 10
struct
{ int i;
double d;
char *p; } *foo;

foo=calloc(FOOS ,sizeof(*foo));

Looking at the piece of code above, brain type A will cry in pain
and quickly change the wrong code to read

foo=malloc(FOOS *sizeof(*foo));
for (i=0;i<FOOS;i++ )
{ foo[i].i=0;
foo[i].d=0;
foo[i].p=NULL; }

since there are architectures where a NULL pointer doesn't have all
bits at 0, so calloc essentially leaves garbage, and maybe there are
also architectures where floating point numbers are represented
differently,
so we also have to set foo.d to 0, and while we are at it, someone
might on day design an architecure where ints also have an unusual
representation, so we do the same for foo.i (or are we lucky and the
standard somewhere says that an integer 0 must be a 0 in memory? ;-)

And then, there's brain type B who sees that the 'correct' version
takes
5 lines instead of 1, reduces readability, maintainability , can be
a source of additional errors and wastes developer life time.
Type B simply uses the 'elegant' calloc approach and trusts in the
laws of physics: even if one night, someone drunk and stoned
creates an architecture that requires the long version,
it will be forced to play a marginal niche role, since an architecture
that is so inherently inefficient that it requires five times as much
code cannot rule the world. Even if Microsoft supports it and tricks
the C standard committee to do the same ;-).

In short, the reason for the success of C is that it gives its users
complete freedom: Brain type A can happily write standard-conform
code that is cluttered but fully portable to the 'CPU' in his/her
vacuum cleaner (and will never know the function mem_freesetnull ),
while brain type B can write 'elegant' code that only works on
'elegant' architectures - but given my many inline Assembly functions,
that's the least of my concerns. So I will just do what brain types B
do:
hide the traces of dirt left in the language by dirty architectures
behind
a macro and keep my mouth shut ;-)

Thanks again for all your comments, I guess everything has been said..

Cheers,
Elmar

May 8 '06 #12
el***@cmbi.ru.n l wrote:
.... snip ...
#define FOOS 10
struct
{ int i;
double d;
char *p; } *foo;

foo=calloc(FOOS ,sizeof(*foo));

Looking at the piece of code above, brain type A will cry in pain
and quickly change the wrong code to read

foo=malloc(FOOS *sizeof(*foo));
for (i=0;i<FOOS;i++ )
{ foo[i].i=0;
foo[i].d=0;
foo[i].p=NULL; }

since there are architectures where a NULL pointer doesn't have all
bits at 0, so calloc essentially leaves garbage, and maybe there are
also architectures where floating point numbers are represented
differently,
I hope not. The intelligent coder will want things to work, so he
will first test the result of the malloc. Then he might well have
other cases in which a foothing needs to be initialiazed, so he
would make the definitions more usable:

struct foo {
int i;
double d;
char *p;
} *foop;

void initfoo(struct foo *foop) {
foop->i = foop->d = 0; foop->p = NULL;
} /* initfoo */

....
if (foop = malloc(FOOS * sizeof *foop))
for (i = 0; i < FOOS; i++) initfoo(foop[i]);
else
/* take corrective action on memory failure */;

.... snip ...
And then, there's brain type B who sees that the 'correct' version
takes
5 lines instead of 1, reduces readability, maintainability , can be
a source of additional errors and wastes developer life time.


Sloppy B simply ignores the problem, and leaves the mess for others
to clean up. He doesn't care if the intermediate consequences are
fatal to anything. He is a certified idiot of little brain. He
doesn't even have the excuse of ignorance.

--
"They that can give up essential liberty to obtain a little
temporary safety deserve neither liberty nor safety."
-- B. Franklin, 1759
"When I want to make a man look like an idiot, I quote him."
-- Mark Twain
"I hear the voices." G W Bush, 2006-04-18

May 8 '06 #13


el***@cmbi.ru.n l wrote On 05/08/06 02:41,:
[...] there are two types of programming brains:

#define FOOS 10
struct
{ int i;
double d;
char *p; } *foo;

foo=calloc(FOOS ,sizeof(*foo));

Looking at the piece of code above, brain type A will cry in pain
and quickly change the wrong code to read

foo=malloc(FOOS *sizeof(*foo));
for (i=0;i<FOOS;i++ )
{ foo[i].i=0;
foo[i].d=0;
foo[i].p=NULL; }

since there are architectures where a NULL pointer doesn't have all
bits at 0, so calloc essentially leaves garbage, and maybe there are
also architectures where floating point numbers are represented
differently,
so we also have to set foo.d to 0, and while we are at it, someone
might on day design an architecure where ints also have an unusual
representation, so we do the same for foo.i (or are we lucky and the
standard somewhere says that an integer 0 must be a 0 in memory? ;-)

And then, there's brain type B who sees that the 'correct' version
takes
5 lines instead of 1, reduces readability, maintainability , can be
a source of additional errors and wastes developer life time.


You've overlooked brain type C, belonging to programmers
who don't allocate memory until there's something they want
to place in it. Such programmers seldom want to "clear" a
piece of allocated memory to anything in particular, either
with calloc() or with memset() or with a loop. Rather, they'll
use the newly-allocated memory to store whatever it was they
allocated it to hold. Filling a block of memory with zeroes
(of whatever kind) usually doesn't advance the state of the
computation very far.

Another thing about type C programmers: They never write
a malloc() or calloc() or realloc() call without also writing
an `if' ...

--
Er*********@sun .com

May 8 '06 #14
> > #define FOOS 10
> struct
> { int i;
> double d;
> char *p; } *foo;
> foo=calloc(FOOS ,sizeof(*foo));

> Looking at the piece of code above, brain type A will cry in pain
> and quickly change the wrong code to read

> foo=malloc(FOOS *sizeof(*foo));
> for (i=0;i<FOOS;i++ )
> { foo[i].i=0;
> foo[i].d=0;
> foo[i].p=NULL; }

> since there are architectures where a NULL pointer doesn't have all
> bits at 0, so calloc essentially leaves garbage, and maybe there are
> also architectures where floating point numbers are represented
> differently,


I hope not. The intelligent coder will want things to work, so he
will first test the result of the malloc.


Indeed, I am not used to the 'brain type A' way of thinking where it's
common to expand the source code with one additional 'if statement' per
memory allocation. Of course the callocs/mallocs above are not those
from libc. (Mine are called mem_alloc and mem_calloc, and I didn't want
to cause additional confusion, but I'll do it from now ;-). Anyway,
mem_alloc and friends do of course never return a NULL pointer.
Instead, you can register emergency cleanup functions (that for example
try to save any open documents) directly in the memory manager. Keep in
mind that if the OS denies even small memory allocation requests, no
program with a decent user interface can continue to do any kind of
useful work. For truly big memory allocations, there's mem_allocnull
and friends, that may return a NULL pointer, which you check and in the
worst case tell the user that this specific operation needs more RAM or
a bigger swap file.
Then he might well have
other cases in which a foothing needs to be initialiazed, so he
would make the definitions more usable:

struct foo {
int i;
double d;
char *p;

} *foop;

void initfoo(struct foo *foop) {
foop->i = foop->d = 0; foop->p = NULL;

} /* initfoo */

I don't agree. If you know the big picture in advance, you also know
that a certain structure is guaranteed to be needed only once, and then
the fooing above just costs your life time and randomizes the code
order.
Sloppy B simply ignores the problem, and leaves the mess for others
to clean up. He doesn't care if the intermediate consequences are
fatal to anything. He is a certified idiot of little brain. He
doesn't even have the excuse of ignorance.


Oups, you missed that at the end of the last posting, I identified
myself as type B. So this insult is not anonymous, but hits me
directly. Please apologize, or I won't reply anymore.

Cheers,
Elmar

May 8 '06 #15
Eric Sosman wrote:
el***@cmbi.ru.n l wrote On 05/08/06 02:41,:
[...] there are two types of programming brains:

#define FOOS 10
struct
{ int i;
double d;
char *p; } *foo;

foo=calloc(FOOS ,sizeof(*foo));

Looking at the piece of code above, brain type A will cry in pain
and quickly change the wrong code to read

foo=malloc(FOOS *sizeof(*foo));
for (i=0;i<FOOS;i++ )
{ foo[i].i=0;
foo[i].d=0;
foo[i].p=NULL; }

since there are architectures where a NULL pointer doesn't have all
bits at 0, so calloc essentially leaves garbage, and maybe there are
also architectures where floating point numbers are represented
differently,
so we also have to set foo.d to 0, and while we are at it, someone
might on day design an architecure where ints also have an unusual
representation, so we do the same for foo.i (or are we lucky and the
standard somewhere says that an integer 0 must be a 0 in memory? ;-)

And then, there's brain type B who sees that the 'correct' version
takes
5 lines instead of 1, reduces readability, maintainability , can be
a source of additional errors and wastes developer life time.
You've overlooked brain type C, belonging to programmers
who don't allocate memory until there's something they want
to place in it. Such programmers seldom want to "clear" a
piece of allocated memory to anything in particular, either
with calloc() or with memset() or with a loop. Rather, they'll
use the newly-allocated memory to store whatever it was they
allocated it to hold. Filling a block of memory with zeroes
(of whatever kind) usually doesn't advance the state of the
computation very far.


Brain type B is also efficient and only used calloc because foo.i and
foo.d will both be used to calculate sums: foo.i will count apples in a
basket, and foo.d will sum up the corresponding weights. foo.p will
hold a list of the individual apple weights. I won't waste your time
with the details how the list is managed, but I can tell you that is
saves type B the burden and source code to actually create the list, if
a function that appends something to a list first checks if the list
pointer is NULL, and in this case creates the list before doing the
work. Just like mem_realloc's ability to accept a NULL pointer saves
you from using mem_alloc first.
In short: mem_calloc was truly needed, otherwise type B would have
certainly not done it ;-)

Another thing about type C programmers: They never write
a malloc() or calloc() or realloc() call without also writing
an `if' ...


Thanks for noting that this little detail was not the original topic
and thus a simplification of little importance. See my other reply
(explaining why type B doesn't use ifs in this context) to the guy who
was less friendly..

Ciao,
Elmar

May 8 '06 #16
el***@cmbi.ru.n l schrieb:
> #define FOOS 10
> struct
> { int i;
> double d;
> char *p; } *foo;

> foo=calloc(FOOS ,sizeof(*foo));

> Looking at the piece of code above, brain type A will cry in pain
> and quickly change the wrong code to read

> foo=malloc(FOOS *sizeof(*foo));
> for (i=0;i<FOOS;i++ )
> { foo[i].i=0;
> foo[i].d=0;
> foo[i].p=NULL; }

> since there are architectures where a NULL pointer doesn't have all
> bits at 0, so calloc essentially leaves garbage, and maybe there are
> also architectures where floating point numbers are represented
> differently,


I hope not. The intelligent coder will want things to work, so he
will first test the result of the malloc.


Indeed, I am not used to the 'brain type A' way of thinking where it's
common to expand the source code with one additional 'if statement' per
memory allocation. Of course the callocs/mallocs above are not those
from libc. (Mine are called mem_alloc and mem_calloc, and I didn't want
to cause additional confusion, but I'll do it from now ;-). Anyway,
mem_alloc and friends do of course never return a NULL pointer.
Instead, you can register emergency cleanup functions (that for example
try to save any open documents) directly in the memory manager. Keep in
mind that if the OS denies even small memory allocation requests, no
program with a decent user interface can continue to do any kind of
useful work. For truly big memory allocations, there's mem_allocnull
and friends, that may return a NULL pointer, which you check and in the
worst case tell the user that this specific operation needs more RAM or
a bigger swap file.


Hmmm, and how do you make sure that you never inadvertently try to
mem_alloc() too much because of an erroneous size computation
beforehand?
In addition, it causes less code changes if the requirements change:
You already have your error handling code in place, have tested it
once, have enough information (no additional parameters to wire the
code with) so that you can change strategy, request a user input,
die gracefully, or whatever is necessary.
I have seen enough huge simulations die on the last couple of time
steps without storing an intermediate state of computation before
dieing for things like forgotten checks after demanding "only a couple
of bytes from the heap"... Reading "paranoia check omitted for speedup"
or similar makes you wish to throttle the culprit...

I started out as type B and made my way over to something between type
A and Eric's type C.
Cleaner algorithms and less maintenance cost leave enough time for
safety checks during run-time and during programming-time :-)

Then he might well have
other cases in which a foothing needs to be initialiazed, so he
would make the definitions more usable:

struct foo {
int i;
double d;
char *p;

} *foop;

void initfoo(struct foo *foop) {
foop->i = foop->d = 0; foop->p = NULL;

} /* initfoo */


I don't agree. If you know the big picture in advance, you also know
that a certain structure is guaranteed to be needed only once, and then
the fooing above just costs your life time and randomizes the code
order.


If it is needed only once, then there is no need for allocation.

Sloppy B simply ignores the problem, and leaves the mess for others
to clean up. He doesn't care if the intermediate consequences are
fatal to anything. He is a certified idiot of little brain. He
doesn't even have the excuse of ignorance.


Oups, you missed that at the end of the last posting, I identified
myself as type B. So this insult is not anonymous, but hits me
directly. Please apologize, or I won't reply anymore.


Well, even though Chuck tends to rather harsh wording, he has a
point here:
I'd rather work with type A or C than with type B as type B's
inadvertent mistakes could cost _my_ lifetime and count against my
frustration tolerance threshold when it comes to a customer fuming
over a stupid mistake costing hours of work.
If type B documented all his or her decisions for more efficient
code together with some reasoning why it is safe to do here, then
this would cost more time than doing all the "overhead stuff" in
the first place.

BTW: It is completely acceptable to make some assumptions like
"8 bit bytes", "2s complement exact width integer types", "all
pointer types have the same type and representation and alignment
requirements", etc. -- if you document them and have a compile
time test module and a run-time test module making sure these
assumptions are justified. Then your code is an island of security.
However, this means that even small parts of the code must be
assumed to rely on these assumptions which may make the code
unusable for projects without the respective assumptions.
For small projects, rewriting may be a good idea; for large
projects, you get your personal regression test nightmare.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
May 8 '06 #17
el***@cmbi.ru.n l wrote:
.... snip ...
Sloppy B simply ignores the problem, and leaves the mess for others
to clean up. He doesn't care if the intermediate consequences are
fatal to anything. He is a certified idiot of little brain. He
doesn't even have the excuse of ignorance.


Oups, you missed that at the end of the last posting, I identified
myself as type B. So this insult is not anonymous, but hits me
directly. Please apologize, or I won't reply anymore.


I addressed myself to the person who ignored the standards, and was
sloppy. I have no control over to whom that applies.

--
"If you want to post a followup via groups.google.c om, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell. org/google/>
Also see <http://www.safalra.com/special/googlegroupsrep ly/>
May 8 '06 #18
el***@cmbi.ru.n l writes:
Eric Sosman wrote:

[...]
Another thing about type C programmers: They never write
a malloc() or calloc() or realloc() call without also writing
an `if' ...


Thanks for noting that this little detail was not the original topic
and thus a simplification of little importance. See my other reply
(explaining why type B doesn't use ifs in this context) to the guy who
was less friendly..


Whether it was the original topic or not, it's an important point, and
it was a bug in the code you posted.

If you want to be a sloppy programmer that's up to you. If you want
to claim that you're doing so because you have a "type B brain",
that's ok too. If you do it in this newsgroup, expect to be
challenged on it.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 8 '06 #19
["Brain Type B":]
#define FOOS 10
struct
{ int i;
double d;
char *p; } *foo;

foo=calloc(FOOS ,sizeof(*foo)); Looking at the piece of code above, brain type A will cry in pain
and quickly change the wrong code to read

foo=malloc(FOOS *sizeof(*foo));
for (i=0;i<FOOS;i++ )
{ foo[i].i=0;
foo[i].d=0;
foo[i].p=NULL; }
And then, there's brain type B who sees that the 'correct' version
takes 5 lines instead of 1, reduces readability, maintainability , can
be a source of additional errors and wastes developer life time. Type
B simply uses the 'elegant' calloc approach [...]


Practically speaking it's much more likely that someone will add a field
to the struct and forget to update the type A setup code (this happens
really quite often) than that the code will get ported to a machine on
which NULL pointers, 0 and 0.0 aren't all represented by zero bits.

There's a saying "premature optimization is the root of all evil".
Premature paranoia is pretty bad too. Anything, premature or not, that
reduces readability or simplicity is going to introduce bugs, and many
of those bugs will work every day on everyday machines.

Sloppiness (e.g. not checking errors at all) is obviously unacceptable;
but the naive conclusion that "the more error or paranoia checking the
better" is almost as bad if it's done at the price of untested error
recovery paths or complex and difficult-to-maintain initialization
routines.
May 8 '06 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

23
22194
by: Ian Tuomi | last post by:
Hello, I was wondering, does it make any difference if you write void foo(int x) { /* insert code here */ } or foo(int x)
14
2471
by: Enrico `Trippo' Porreca | last post by:
Given: typedef struct Node Node; struct Node { void *obj; Node *next; }; typedef struct Stack Stack; struct Stack {
188
17422
by: infobahn | last post by:
printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */
14
3021
by: arun | last post by:
Hi, Why sizeof operator when applied on void returns one when compiled with gcc compiler ??. When i tried it on VC++ compiler, it gives an error. But another version of the VC++ compiler on my friend's machine gives it as zero. Have anyone tried this ? I believe it should give an error because i think there is nothing called void. Regards, arun..
28
16457
by: Peter Olcott | last post by:
I want to make a generic interface between a scripting language and native code, the native code and the interpreter will both be written in C++. The interpreter will probably be implemented as a subset of C/C++, thus will have the same syntax as C/C++. Somehow the interpreted code must be able to store generic function pointers because there is no way for the interpreter to know every possible function signature in advance. I was...
160
5670
by: raphfrk | last post by:
Is this valid? int a; void *b; b = (void *)a; // b points to a b += 5*sizeof(*a); // b points to a a = 100;
0
9487
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9297
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9904
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9884
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7285
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6556
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5168
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
3
3395
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2697
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.